|
| 1 | +""" |
| 2 | +Time Complexity: O(n * k * m) |
| 3 | + - n = len(s) |
| 4 | + - k = number of words in wordDict |
| 5 | + - m = average word length in wordDict |
| 6 | +
|
| 7 | + At each index in s, we may check every word in wordDict and for each, compare up to m characters. |
| 8 | +
|
| 9 | +Space Complexity: O(n) |
| 10 | + - n = len(s), due to recursion stack and memoization table (one entry per possible starting index). |
| 11 | +
|
| 12 | +- Uses top-down dynamic programming with memoization (via lru_cache). |
| 13 | +- The helper function dp(index) returns True if s[index:] can be fully segmented into words from wordDict. |
| 14 | +- Base case: If index == len(s), then the entire string is successfully segmented. |
| 15 | +- For each call, iterate through all words in the dictionary and check if s[index:] begins with that word. |
| 16 | +- If a match is found, recursively check for the remainder of the string starting after the matched word. |
| 17 | +- Return True as soon as any valid segmentation is found. |
| 18 | +- Return False if no segmentation is possible for this index. |
| 19 | +""" |
| 20 | +class Solution: |
| 21 | + def wordBreak(self, s: str, wordDict: List[str]) -> bool: |
| 22 | + @lru_cache() |
| 23 | + def dp(index: int) -> bool: |
| 24 | + if index == len(s): |
| 25 | + return True |
| 26 | + |
| 27 | + for word in wordDict: |
| 28 | + if len(s) - index < len(word): |
| 29 | + continue |
| 30 | + |
| 31 | + if s[index:].startswith(word) and dp(index + len(word)): |
| 32 | + return True |
| 33 | + |
| 34 | + return False |
| 35 | + |
| 36 | + return dp(0) |
| 37 | + |
| 38 | +""" |
| 39 | +Time Complexity: O(n * k * m) |
| 40 | + - n = len(s) |
| 41 | + - k = number of words in wordDict |
| 42 | + - m = average word length in wordDict |
| 43 | +
|
| 44 | + For every index in s, we consider each word in wordDict and, for each, match up to m characters. |
| 45 | +
|
| 46 | +Space Complexity: O(n) |
| 47 | + - n = len(s), required for the dp array. |
| 48 | +
|
| 49 | +- Uses bottom-up dynamic programming. |
| 50 | +- The dp array indicates whether a prefix of s up to index can be segmented into words from wordDict. |
| 51 | +- Base case: dp[0] = 1, since the empty string can always be segmented. |
| 52 | +- For each index, iterate through all words, and for each, check if s[index - W : index] equals the word, assuming index >= W and dp[index - W] is True. |
| 53 | +- If a match is found, update dp[index] to reflect that segmentation. |
| 54 | +- Finally, return True if dp[-1] is set, indicating the entire string can be segmented; otherwise, return False. |
| 55 | +""" |
| 56 | +class Solution: |
| 57 | + def wordBreak(self, s: str, wordDict: List[str]) -> bool: |
| 58 | + S = len(s) |
| 59 | + |
| 60 | + dp = [0] * (S + 1) |
| 61 | + dp[0] = 1 |
| 62 | + |
| 63 | + for index in range(S + 1): |
| 64 | + for word in wordDict: |
| 65 | + W = len(word) |
| 66 | + if index < W or dp[index - W] == 0: |
| 67 | + continue |
| 68 | + if s[index - W :].startswith(word): |
| 69 | + dp[index] = dp[index - W] |
| 70 | + |
| 71 | + return bool(dp[-1]) |
0 commit comments