November 2, 2024
Starting with a hard problem today.
1class Solution:2 def findSubstring(self, s: str, words: List[str]) -> List[int]:3 lenTotal = len(''.join(words))4 perms = set()5 def permutations(head, tail):6 if not len(head):7 perms.add(tail)8 for i in range(len(head)):9 permutations(head[:i] + head[i+1:], tail + head[i])10 permutations(words, '')1112 result = []13 for i in range(0, len(s)):14 if s[i:i+lenTotal] in perms:15 result.append(i)1617 return result
This solution times out. It has a time complexity of O(n) = n! due to the permutations method.
I'm going to try again using python's itertools.permutations
method. However, this lead to an out of memory error.
Rethinking the algorithm, we can remove the step where we find all permutations. Instead, we will replace our perms
set with a method called validSubstring(substring)
. This method will use a copy of the list of words, and we will loop through the substring and remove any word occurrences. If we always find a word at each step in our substring, we return True. We improve the efficiency of our algorithm by caching the result of each substring as either validSubstring
or invalidSubstring
set members. This solution is accepted.
1import itertools23class Solution:4 def findSubstring(self, s: str, words: List[str]) -> List[int]:5 if len(s) < len(''.join(words)):6 return []78 wordLen = len(words[0])9 def validSubstring(substring):10 wordsTemp = words[:]11 for i in range(0, len(substring), wordLen):12 currWord = substring[i:i + wordLen]13 if currWord in wordsTemp:14 wordsTemp.remove(currWord)15 else:16 return False17 return True1819 invalidSubstrings = set()20 validSubstrings = set()21 wordsLen = wordLen * len(words)22 window = s[:wordsLen]23 res = []24 if validSubstring(window):25 validSubstrings.add(window)26 res.append(0)2728 for i in range(wordsLen, len(s)):29 letter = s[i]30 window = window[1:]31 window += letter32 if window not in invalidSubstrings:33 if window in validSubstrings or validSubstring(window):34 res.append(i - wordsLen + 1)35 validSubstrings.add(window)36 else:37 invalidSubstrings.add(window)3839 return res40```41The time complexity is O(n) = n * k^2 where k is the number of words. It is k^2 because we loop through k words and the remove operation is O(k) = k.
LeetCode 68. Text Justification
LeetCode 76. Minimum Window Substring