day27
39.组合总和
题目链接:39. 组合总和
使用递归三部曲,首先定义两个变量一个存储结果二维数组,一个存储路径,然后定义函数的参数,一共有四个,一个记录数组,一个记录目标值,一个记录sum值,一个记录开始变量。中间有递归和回溯的过程。
class Solution {
public:
// 全局变量存放结果
vector<int> path;
vector<vector<int>> result;
// 确定返回值和参数
void backtracking(vector<int>& candidates,int target,int sum, int startIndex){
// 确定终止条件
if( sum > target) return;
if( sum == target ){
result.push_back(path);
return ;
}
// 确定单层递归逻辑
for( int i = startIndex; i < candidates.size() && sum+candidates[i]<=target; i++){
// 保存结果
path.push_back(candidates[i]);
sum += candidates[i];
// 递归
backtracking(candidates,target,sum, i); //这块不加1是因为题目中说可以无限制重复选取
//回溯
path.pop_back();
sum -= candidates[i];
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
int sum = 0;
int startIndex = 0;
sort(candidates.begin(),candidates.end()); //剪枝需要排序
backtracking(candidates,target,sum,startIndex);
return result;
}
};
40.组合总和II
题目链接:40. 组合总和 II
去重之前需要对nums进行排序,for控制横向,递归控制纵向,其他的和之前的组合问题一样
class Solution {
public:
// 存储结果
vector<int> path; //存储路径
vector<vector<int>> result; //存储最终结果
// 确定返回值和参数
void backtracking( vector<int>& nums,int target, int sum, int startIndex,vector<bool>& used){
// 确定终止条件
if( sum > target ) return ;
if( sum == target ){
result.push_back(path);
return;
}
// 确定单层逻辑
for( int i = startIndex; i < nums.size() && sum+nums[i] <=target; i++){
// 去重操作
if( i > 0 && nums[i] == nums[i-1] && !used[i-1]) continue; //前一个元素没有被用过
path.push_back(nums[i]); //添加元素
sum += nums[i];
used[i] = true;
backtracking( nums,target,sum,i+1,used);
sum -= nums[i];
used[i] = false;
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
vector<bool> used(candidates.size(),false);
backtracking( candidates,target,0,0,used);
return result;
}
};
131.分割回文串
题目链接:131. 分割回文串
首先确定终止条件,这里startIndex可以理解为切割线,只要切割线大于等于s.size()也就是切割线到最后了,就将path的结果加入result,回文串用双指针判断,其他模板与组合之前的回溯模板相同。
class Solution {
public:
// 判断回文串
bool isPalinrome(const string& s,int startIndex, int i){
int left = startIndex;
int right = i;
while( left <= right){
if(s[left] != s[right]) return false;
left++;
right--;
}
return true;
}
// 递归函数
vector<string> path;
vector<vector<string>> result;
void backTracking(const string&s,int startIndex){
// 确定终止条件
if( startIndex >= s.size() ){ //如果切割点到了size()这,就加入,判断回文逻辑放下面
result.push_back(path);
return;
}
for( int i = startIndex; i < s.size(); i++){
if( isPalinrome(s,startIndex,i) ){ //判断是否回文
string str = s.substr(startIndex , i - startIndex + 1); // 开始startIndex, 第二个参数是截取的数量
path.push_back(str);
}
else{ continue;}
backTracking(s,i+1);
path.pop_back();
}
}
vector<vector<string>> partition(string s) {
backTracking( s,0);
return result;
}
};