39. 组合总和 - 力扣(LeetCode)
思路:回溯算法,在s<0时可以做剪枝操作
重点:因为可以重复取同一个值,所以每次的开始位置不用加一
class Solution {
public:
vector<vector<int>>ans;
vector<int>path;
void dfs(vector<int>& cand,int s,int index){
if(s<0){
return;
}
if(s==0){
ans.push_back(path);
return;
}
for(int i=index;i<cand.size();i++){
path.push_back(cand[i]);
dfs(cand,s-cand[i],i);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
dfs(candidates,target,0);
return ans;
}
};
40. 组合总和 II - 力扣(LeetCode)
思路:不可选重复元素,采用的t数组记录前一层递归是否使用了,为true表示同一树枝使用了,树枝下一层还可以使用,为false表示在同一树层,需要跳过重复值
重点:额外数组记录是否选取过
class Solution {
public:
vector<vector<int>>ans;
vector<int>path;
void dfs(vector<int>& cand,int s,int index,vector<bool>& t){
if(s==0){
ans.push_back(path);
return;
}
for(int i=index;i<cand.size()&&s-cand[i]>=0;i++){
if(i>0&&cand[i]==cand[i-1]&&t[i-1]==false){
continue;
}
path.push_back(cand[i]);
t[i]=true;
dfs(cand,s-cand[i],i+1,t);
t[i]=false;
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
vector<bool>t(candidates.size(),false);
dfs(candidates,target,0,t);
return ans;
}
};
131. 分割回文串 - 力扣(LeetCode)
思路:回溯算法,切割为子字符串,判断是否为回文串,是就记录,当起始位置大于等于原字符串的长度时,表示到叶子结点切割完成
class Solution {
public:
vector<vector<string>>ans;
vector<string>path;
bool ishui(string word,int l,int r){
while(l<r){
if(word[l]!=word[r]){
return false;
}
l++,r--;
}
return true;
}
void dfs(string& s,int index){
if(index>=s.size()){
ans.push_back(path);
return;
}
for(int i=index;i<s.size();i++){
if(ishui(s,index,i)){
string t=s.substr(index,i-index+1);
path.push_back(t);
}else{
continue;
}
dfs(s,i+1);
path.pop_back();
}
}
vector<vector<string>> partition(string s) {
dfs(s,0);
return ans;
}
};
总结
选好递归终止条件,了解同一树层和同一树枝。