LeetCode/solutions/139. Word Break.md

64 lines
2.6 KiB
Markdown
Raw Normal View History

2019-08-10 09:32:28 +00:00
# [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<string>&dict, vector<int>&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<string>& wordDict) {
unordered_set<string>dict(wordDict.begin(), wordDict.end());
vector<int>cache(s.size(), -1);
return DFS(s, 0, dict, cache);
}
};
```
## 思路二
```C++
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set<string>dict(wordDict.begin(), wordDict.end());
vector<int>dp(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;
}
};
```