39. 组合总和
class Solution {
public:vector<int> path;vector<vector<int>> res;void func(vector<int>& candi, int target, int sum,int st){if(sum == target){res.push_back(path);return;}for(int i = st; i < candi.size(); ++i){if(sum > target) break;sum += candi[i];path.push_back(candi[i]);func(candi,target,sum,i);sum -= candi[i];path.pop_back();}}vector<vector<int>> combinationSum(vector<int>& candidates, int target) {func(candidates,target,0,0);return res;}
};
就是正常的套公式,因为不存在重复元素,很简单。
40.组合总和II
class Solution {
public:vector<int> path;vector<vector<int>> res;void func(vector<int>& candidates,int target, int sum, int st,vector<bool>& used){if(sum > target) return;if(sum == target){res.push_back(path);return;}for(int i = st; i < candidates.size(); ++i){if(i>0 && candidates[i] == candidates[i-1] && used[i-1] == false) continue;//break有问题sum += candidates[i];path.push_back(candidates[i]);used[i] = true;func(candidates,target,sum,i+1,used);sum -= candidates[i];path.pop_back();used[i] = false;}}vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {sort(candidates.begin(),candidates.end());vector<bool> used(candidates.size(),false);func(candidates,target,0,0,used);return res;}
};
used数组的初次使用,主要就是用来去重,当同一数层时候,前面相同的为0,表示之前用过,则跳过当前,若前面相同且bool为1,代表在递归中,其虽然相同但是还是在结果的获取中,不能跳过。
以及需要考虑used别忘了传引用,且每次回溯需要更改used值,老是容易忘。
131.分割回文串
class Solution {
public:vector<string> path;vector<vector<string>> res;bool isH(string s, int st, int end){while(st < end){if(s[st] != s[end]) return false;st++;end--;}return true;}void func(string s, int st){if(st >= s.size()){res.push_back(path);return;} for(int i = st; i < s.size(); ++i){if(isH(s,st,i)){// string s_sub = ;path.push_back(s.substr(st,i-st+1));}else continue;func(s,i+1);path.pop_back();}}vector<vector<string>> partition(string s) {func(s,0);return res;}
};
具体思路:
在上面需要明确一个点,原始的 st 一直是头部,而流动的 i 则是用来改变切割的长度,当然切割也不是真的切割, substr 只是截取,sub(i,len)从i截取len长度的字符串。
而最开始写错的,将func放进 if为ture里,其实根本没必要,因为如果为false,就continue,也根本不会进入递归。