这道题思路不难想,但是代码却改了好几次才通过,最主要的问题是会出现超时间/超内存
第一种方式:
利用动态规划—超时间限制,因为有很多没有利用到的状态也被计算了,这些状态也都被计算了下来
class Solution {public:vector<string> wordBreak(string s, vector<string>& wordDict) {int n = s.size();vector<vector<vector<string>>> dp(n, vector<vector<string>>(n));for(int len = 1; len <= n; len++){for(int l = 0; l < n; l++){int r = l + len - 1;if(r >= n) break;string sub = s.substr(l, r - l + 1);if(find(wordDict.begin(), wordDict.end(), sub) != wordDict.end()){dp[l][r].push_back(sub);}for(int k = l; k < r; k++){if(dp[l][k].size() && dp[k + 1][r].size()){for(auto x: dp[l][k])for(auto y: dp[k+1][r]){string tmp = x + " " + y;dp[l][r].push_back(tmp);}}}}}vector<string> res;sort(dp[0][n - 1].begin(), dp[0][n - 1].end());for(auto x: dp[0][n - 1]){if(!res.size() || x != res.back())res.push_back(x);}return res;}};
dp—超内存限制 原因是到最后了才发现最后面的拼不起来啊,那个恨,前面的都浪费了
class Solution {public:vector<string> wordBreak(string s, vector<string>& wordDict) {int n = s.size();vector<vector<string>> dp(n);for(int i = 0; i < s.size(); i++){string sub = s.substr(0, i - 0 + 1);if(find(wordDict.begin(), wordDict.end(), sub) != wordDict.end()){dp[i].push_back(sub);}for(int j = i; j > 0; j--){string sub = s.substr(j, i - j + 1);//[j, i]if(find(wordDict.begin(), wordDict.end(), sub) != wordDict.end() && dp[j - 1].size()){for(auto x: dp[j - 1]){dp[i].push_back(x + " " + sub);}}}}return dp[n - 1];}};
dfs—先扫一次到最后看看能不能拼起来,如果能拼起来再拼起来,并且可以去利用set加快搜索速度
class Solution {string s;set<string> wordDict;map<int, vector<string>> mp;vector<int> v;void dfs(int start){if(start == s.size()){v[start] = 1;mp[start] = {""};return;}if(v[start] != -1)//说明已经访问过了{return;}vector<string> res;for(int k = start; k < s.size(); k++){string sub = s.substr(start, k - start + 1);if(wordDict.count(sub)){dfs(k + 1);if(v[k+1] == 0) continue;for(auto x: mp[k+1]){if(x.size())res.push_back(sub + " " + x);elseres.push_back(sub);}}}if(res.size()){v[start] = 1;mp[start] = res;}else{v[start] = 0;}return;}public:vector<string> wordBreak(string _s, vector<string>& _wordDict) {s = _s;for(auto x:_wordDict)wordDict.insert(x);v = vector<int>(s.size() + 1, -1);//-1没有搜索, 0 不行 1可以dfs(0);vector<string> tmp = mp[0];if(tmp.size())return tmp;elsereturn vector<string>();}};
第二次写题
class Solution {vector<vector<string>> res;//这里相当于保存记录,防止多次调用vector<int> mask;//这里相当于记录这个idx开始的是否被访问过set<string> st;void dfs(string s, int idx){if(idx == s.size()) return;for(int i = idx; i < s.size(); i++){string str = s.substr(idx, i - idx + 1);if(st.find(str) != st.end()){//这里有意思,这里可以实现先后面的if(mask[i + 1] == -1) dfs(s, i + 1);//然后再回来这里进行拼接for(auto x: res[i + 1]){//这里有两种情况,因为如果是最后就不用加' 'if(x != "")res[idx].push_back(str + ' ' + x);elseres[idx].push_back(str);}}}//做一下标记,这个idx已经被找过了mask[idx] = 1;}public:vector<string> wordBreak(string s, vector<string>& wordDict) {if(!s.size()) return vector<string>();res.resize(s.size() + 1);res[s.size()]= {""};mask.resize(s.size() + 1, -1);mask[s.size()] = 1;for(auto x: wordDict){if(st.find(x) == st.end())st.insert(x);}//下面这里是想看有没有在s出现的字母没有出现在wordDict里面//如果在s出现在wordDict没有出现,那肯定匹配不上set<char> worddic;set<char> word;for(auto x: s){if(word.find(x) == word.end())word.insert(x);}for(auto x: st){for(auto c: x){if(worddic.find(c) == worddic.end())worddic.insert(c);}}for(auto x: word){if(worddic.find(x) == worddic.end())return vector<string>();}//dfsdfs(s, 0);//返回 res是二维的,所以这里返回的是第一个return res[0];}};
第三次写题
class Solution {vector<vector<string>> res;vector<bool> mask;set<string> dict;void dfs(string s, int idx){if(idx >= s.size()) return;if(mask[idx] == false) return;mask[idx] = false;for(int i = idx; i < s.size(); i++){string str = s.substr(idx, i - idx + 1);if(dict.find(str) == dict.end()) continue;dfs(s, i + 1);for(auto x: res[i + 1]){string ns = str + (x==""? "":' '+x);res[idx].push_back(ns);}}}public:vector<string> wordBreak(string s, vector<string>& wordDict) {if(!s.size()) return vector<string>();res.resize(s.size() + 1);mask = vector<bool>(s.size() + 1, true);res[s.size()] = {""};mask[s.size()] = false;for(auto w: wordDict){if(dict.find(w) == dict.end())dict.insert(w);}dfs(s, 0);return res[0];}};
需要注意的是加了一段利用char来先筛选的,会让使用的内存数量减小,从17.2M->13.2M
class Solution {
vector<vector<string>> res;
vector<bool> mask;
set<string> dict;
void dfs(string s, int idx)
{
if(idx >= s.size()) return;
if(mask[idx] == false) return;
mask[idx] = false;
for(int i = idx; i < s.size(); i++)
{
string str = s.substr(idx, i - idx + 1);
if(dict.find(str) == dict.end()) continue;
dfs(s, i + 1);
for(auto x: res[i + 1])
{
string ns = str + (x==""? "":' '+x);
res[idx].push_back(ns);
}
}
}
public:
vector<string> wordBreak(string s, vector<string>& wordDict) {
if(!s.size()) return vector<string>();
res.resize(s.size() + 1);
mask = vector<bool>(s.size() + 1, true);
res[s.size()] = {""};
mask[s.size()] = false;
for(auto w: wordDict)
{
if(dict.find(w) == dict.end())
dict.insert(w);
}
//和上面的比,加了这一段
set<char> worddic;
set<char> word;
for(auto x: s)
{
if(word.find(x) == word.end())
word.insert(x);
}
for(auto x: dict)
{
for(auto c: x)
{
if(worddic.find(c) == worddic.end())
worddic.insert(c);
}
}
for(auto x: word)
{
if(worddic.find(x) == worddic.end())
return vector<string>();
}
//
dfs(s, 0);
return res[0];
}
};
