139. 单词拆分以及字符串递归经验:传入右子串
问题
给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。
注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。
分析
拆分字符串,判断拆分得到的子串是否在dict中。显然,dfs,需要回溯。超时,需要记忆。递推还没想怎么写,不如递归好写。
经验:字符串与递归结合,将右子串作为参数即可,不需要左右边界
代码
// 返回值递归,比全局变量递归剪枝,35/47,加了记忆后如下,可以通过
class Solution {
public:
int s_n = 0;
vector<string> d;
unordered_set<string> us;
unordered_map<string, bool> mem;
// 经验:字符串与递归结合,将右子串作为参数即可,不需要左右边界
bool dfs(string left_s) {
if (mem.find(left_s) != mem.end()) {return mem[left_s];}
if (us.find(left_s) != us.end()) {mem.insert(make_pair(left_s, true)); return true;}
int left_s_n = left_s.size();
for (int i = 1; i <= left_s_n; i++) {
if (us.find(left_s.substr(0, i)) != us.end()) {
if (dfs(left_s.substr(i))) {
mem.insert(make_pair(left_s, true));
return true;
};
mem.insert(make_pair(left_s, false));
}
}
return false;
}
bool wordBreak(string s, vector<string>& wordDict) {
this->d = wordDict;
s_n = s.size();
for (int i = 0; i < wordDict.size(); i++) {
us.insert(wordDict[i]);
}
bool res = dfs(s);
return res;
}
};
补一个全局变量递归。
// 法一、全局变量递归,最慢,35 / 47 个通过的测试用例
class Solution {
public:
bool res = false;
int s_n = 0;
vector<string> d;
unordered_set<string> us;
void dfs(string left_s) {
if (us.find(left_s) != us.end()) {res = true; return;}
int left_s_n = left_s.size();
for (int i = 1; i <= left_s_n; i++) {
if (us.find(left_s.substr(0, i)) != us.end()) {
dfs(left_s.substr(i));
}
}
}
bool wordBreak(string s, vector<string>& wordDict) {
this->d = wordDict;
s_n = s.size();
for (int i = 0; i < wordDict.size(); i++) {
us.insert(wordDict[i]);
}
dfs(s);
return res;
}
};

浙公网安备 33010602011771号