diff --git a/solutions/139. Word Break.md b/solutions/139. Word Break.md new file mode 100644 index 0000000..267ca58 --- /dev/null +++ b/solutions/139. Word Break.md @@ -0,0 +1,63 @@ +# [139. Word Break](https://leetcode.com/problems/word-break/) +# 思路 +## 思路一 DFS +此题最好想的就是用hashset记录词典以加快查找速度, 再用一个DFS即可解决. 但由于DFS里面存在很多重复计算, 所以计算复杂度很高, 亲测是会超时的. + +为了避免这些重复计算, 我们可以用一个长度和字符串s等长的数组cache(初始化全为-1)来记录之前已经计算的过程.其中cache[i]=1表示s[i,i+1,...]是一个 +可以拆开的字符串, 则cache[i]=0表示s[i,i+1,...]是一个拆不开的字符串.然后就可以DFS了, 我们假设s[0, 1,..., start-1]是可以拆开的, DFS函数 +的内容就是判断从start开始的s的子串是否可以拆开, 那么DFS函数可以这样组织: +* 如果start到达末尾了, 那即可返回true; +* 如果cache[start]不为-1, 说明之前计算过从start开始的子串是否可以拆开, 所以直接返回cache的结果即可; +* 否则就需要进行循环递归了, 得到结果后需要对cache[start]写入合适的值. + +## 思路二 动态规划 +思路一使用了cache数组, 就有点动态规划的意思了. 这里我们使用一个长度为s长度加一的dp数组, +将dp最后一个值初始化为1其他全部初始化为0, 意义和思路一中cache代表的意义一样. 那么我们就可以从后往前开始遍历并进行和思路一同样的动归了. + + +# C++ +## 思路一 +``` C++ +class Solution { +private: + bool DFS(string &s, int start, unordered_set&dict, vector&cache){ + if(start == s.size()) return true; + if(cache[start] != -1) return cache[start]; + + for(int i = start; i < s.size(); i++){ + if(dict.count(s.substr(start, i - start + 1)) && DFS(s, i + 1, dict, cache)){ + cache[start] = 1; + return true; + } + } + cache[start] = 0; + return false; + } +public: + bool wordBreak(string s, vector& wordDict) { + unordered_setdict(wordDict.begin(), wordDict.end()); + vectorcache(s.size(), -1); + return DFS(s, 0, dict, cache); + } +}; +``` + +## 思路二 +```C++ +public: + bool wordBreak(string s, vector& wordDict) { + unordered_setdict(wordDict.begin(), wordDict.end()); + vectordp(s.size() + 1, 0); + dp[s.size()] = 1; + for(int start = s.size(); start >= 0; start--){ + for(int i = start; i < s.size(); i++){ + if(dp[i+1] && dict.count(s.substr(start, i-start+1))){ + dp[start] = 1; + break; + } + } + } + return dp[0] == 1; + } +}; +```