题解
Medium
动态规划
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
// a + b = s
// as long as a true and b true, then s true
// dp[i]: i represents the sub string from 0 to i
// find dp[n-1]
vector<bool> dp(s.size()+1, false);
dp[0] = true; // assume an empty word is always existing in dict
for(int i = 1; i <= s.size(); i++) {
for(int j = 0; j < i; j++) {
if(dp[j] && find(wordDict.begin(), wordDict.end(), s.substr(j, i-j)) != wordDict.end()) {
dp[i] = true;
break;
}
}
}
return dp[s.size()];
}
};
递归加记忆
这是很经典很有代表性的一题,可以用多种方法做出来。当然,最佳方法是用动态规划。
应该几种方法多试一下,在面试环境下,不一定能够第一时间找到最佳方法,最好有第二解法做候补。
其实这种题,能用动态规划来做,往往就能用回溯加记忆矩阵的方法来做,记忆矩阵这里充当了动态规划矩阵的作用,思想是一样的,“不必重复去解决已解决的问题”。只不过动态规划在代码上显得更舒服一些。
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set wordSet(wordDict.begin(), wordDict.end());
vector<int> memo(s.size(), -1);
return helper(s, wordSet, 0, memo);
}
bool helper(string s, unordered_set<string>& wordSet, int start, vector<int>& memo) {
// memo[i]: the substring form i to size-1
if(start == s.size()) return true; // empty word
// first check if this has been solved before
if(memo[start] != -1) return memo[start];
// divide problem into start to i, and i to end
for(int i = start; i <= s.size(); i++) {
if(wordSet.count(s.substr(start, i-start)) && helper(s, wordSet, i, memo)) {
memo[start] = 1;
return true;
}
}
memo[start] = 0;
return false;
}
};