39. 组合总和
思想:套模板,递归逻辑中的for循环里下一层的递归函数参数开始位置和这一层的参数位置一样,保证同一个数字可以无限制重复被选取。
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(int target,int index,vector<int>& candidates){
//结束条件
if(target==0){
result.push_back(path);
return;
}
//if(target<0) return;
for(int i = index; i<candidates.size()&& target>=0;i++){
path.push_back(candidates[i]);
backtracking(target-candidates[i],i,candidates);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtracking(target,0,candidates);
return result;
}
};
40.组合总和II
思想:首先需要排序,在递归的单层逻辑中,要对于数字重复的情况进行筛选。如果当前编号为1,前一个编号也为1,则需要分情况讨论。如果是在同一层(即同一个for循环)中访问到的,那么前一个1所获得的数组已经包含了当前1可获得的所有情况,甚至还包含了这个1本身,所以应该跳过当前的1.但如果是在下一层循环中遇到了当前的1,说明这两个1是在同一个组合中出现的,这并不冲突,比如说[1,1],该情况是合法的,不需要跳过。这就是所谓的树层遍历和树枝遍历。为了区分这两种情况,我们可以在回溯中设置一个bool类型的数组来储存当前的访问情况,如果位置i和位置i-1的值相同,而且位置i对应的bool为1,说明i-1这个值被访问过了,为树枝遍历,可以继续。如果bool为0,则说明当前为树层遍历,当前答案数组中并未包含前一个i,所以i的全部情况以及被前一个i包括了,则跳过当前的遍历,i直接+1.
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(int index, int target, vector<int>& candidates, vector<bool> verify){
if(target==0){
result.push_back(path);
return;
}
if(target<0)return;
//树层和树枝,如果前后两个数相同 而且前一个数为0,则说明这两个值在同一层,此时应该跳过
//如果前一个数为1,则说明这两个值在同一个树枝上,符合条件,不用跳过。
for(int i = index;i<candidates.size();i++){
verify[i] = 1;
if(i>0&&candidates[i]==candidates[i-1]&&verify[i-1]==0){
verify[i]=0;
continue;
}
path.push_back(candidates[i]);
backtracking(i+1,target-candidates[i],candidates,verify);
path.pop_back();
verify[i] = 0;
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<bool> verify(candidates.size(),0);
sort(candidates.begin(),candidates.end());
backtracking(0,target,candidates,verify);
return result;
}
};
131.分割回文串
思想:在插入答案数组之前首先要判断当前字符串是不是回文串,所以应该写一个判断回文串的函数,如果满足条件的话则进行插入。结束条件:当前访问的位置大于等于总字符串的长度。其他地方也是直接套模板就可以。如果字串当前不满足回文串时,就会一直回退,所以不需要担心出现不满足每个子串都是回文串的情况。
难点:不知道怎么初始化字串,搜了一下,string s1 = s.substr(index, i - index + 1)。
class Solution {
public:
vector<string> path;
vector<vector<string>> result;
bool judge(string s){
for(int i = 0;i<s.size()/2;i++){
if(s[i]!=s[s.size()-1-i]) return false;
}
return true;
}
void backtracking(string s,int index){
// if(index>s.size()) return;
if(index>=s.size()){
result.push_back(path);
return;
}
int start = index;
for(int i =index;i<s.size();i++){
string s1 = s.substr(index, i - index + 1);
if(judge(s1)){
path.push_back(s1);
backtracking(s,i+1);
path.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
backtracking(s,0);
return result;
}
};