139. Word Break
題目網址:https://leetcode.cn/problems/word-break/
題意:給一 string
s
和一 string listwordDict
, 若wordDict
中的單字能組出s
則返回true
。注意:
wordDict
中的 string 互不相同, 且s.length ≤ 300
Solution 1:
想法:利用 DP, 其中
dp[i]
代表s[0~(i-1)]
是否能被拆分成若干個出現在wordDict
中的單字, 我們要枚舉s[0~(i-1)]
中的切割點j
, 使得s[0~(j-1)]
和s[j~(i-1)]
皆在wordDict
中, 由於j < i
, 所以要計算dp[i]
時可透過先前計算過的d[j]
知道s[0~j]
是否能被拆分, 然後再判斷s[j~(i-1)]
是否在wordDict
中即可, 故得到以下公式:
dp[i] = dp[j] && check(s[j~(i-1)])
check(s[j~(i-1)])
代表檢查s[j~(i-1)]
是否在wordDict
中
class Solution { |
- time:$O(n^2)$ ➔ for loop
- space:$O(n)$ ➔
dp
Solution 2:(TLE 無法通過)
想法:利用 DFS + Trie
class TrieNode{ |
time:$O(\sum_{i = 0}^{m-1}{w_i} + 2^n)$, 其中 $m$ 為
wordDict
中單字的個數, $w_i$ 為wordDict[i]
的長度, $n$ 為s
的長度$O(\sum_{i = 0}^{m-1}{w_i})$:將
wordDict
中每個單字 insert 到 trie 中$O(2^{n})$:判斷長度為
n
的s
能否拆分成其他單字。$T(n) = T(n - 1) + T(n - 2) + … + T(1)$
space:$O(\sum_{i = 0}^{m-1}{w_i})$ ➔ $O(26 \cdot \sum_{i = 0}^{m-1}{w_i})$, worse case:trie 中所有單字都沒有重複的 prefix
Solution 3:
想法:利用 DFS + Trie + DP, 改進 Solution 2, 若
s
中idx = cur
為開頭往後的 substring 無法由若干個wordDict[i]
所組成, 則透過memo
紀錄起來, 藉此來進行 pruning, 避免重複走失敗的道路
class TrieNode{ |
- time:$O(\sum_{i = 0}^{m-1}{w_i} + n^2)$, 其中 $m$ 為
wordDict
中單字的個數, $w_i$ 為wordDict[i]
的長度, $n$ 為s
的長度- $O(\sum_{i = 0}^{m-1}{w_i})$:將
wordDict
中每個單字 insert 到 trie 中 - $O(n^2)$:判斷長度為
n
的s
能否拆分成其他單字- $O(n^2)$ : $T(n) = T(n - 1) + O(n)$, 因為有用
memo
記憶, 所以呼叫 $T(n-1)$ 即可, 因為 $T(n-1)$ 會再往下呼叫 $T(n-2)$, 依此類推 …, 每個 $T(n-i)$ 只要呼叫一次即可(因為會記住結果)。 - $O(n)$ 是因為呼叫一次 $T(n-1)$ 後, 剩下 $T(n-2), …, T(1)$ 都會計算出來。原本 $O(n)$ 應寫作 $T(n-2) + T(n-3) + … +T(1)$, 但是除了 $T(n-1)$, 剩下的 $T(n-i)$ 都只需 $O(1)$, 故 $T(n-2) + T(n-3) + … +T(1)$ 可直接寫成 $O(n)$。
- $O(n^2)$ : $T(n) = T(n - 1) + O(n)$, 因為有用
- $O(\sum_{i = 0}^{m-1}{w_i})$:將
- space:$O(\sum_{i = 0}^{m-1}{w_i})$ ➔ $O(26 \cdot \sum_{i = 0}^{m-1}{w_i})$ + $O(1)$
- $O(26 \cdot \sum_{i = 0}^{m-1}{w_i})$:worse case:trie 中所有單字都沒有重複的 prefix
- $O(1)$:
memo
為常數空間