void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
**
1.元素不重复,每个只能取一次
**
例题:leetcode 46.全排列
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
** 输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]**
class Solution {
public:
// 路径:记录在 path 中
// 选择列表:nums 中不存在于path 的那些元素(used[i] 为 false)
// 结束条件:nums 中的元素全都在 path 中出现
vector<vector<int>>res;
vector<int>path;
void backtrack(vector<int>& nums,vector<int> used){
if(path.size()==nums.size()){//触发结束条件
res.push_back(path);//收集结果
return;//记得返回
}
//单层搜索
for(int i=0;i<nums.size();i++){
// 排除不合法的选择
if(used[i]==1)continue;// nums[i] 已经在 path 中,跳过
// 做选择
path.push_back(nums[i]);
//记录nums[i]否用过
used[i]=1;
// 进入下一层决策树
backtrack(nums,used);
//回溯,取消选择撤销处理结果
path.pop_back();
used[i]=0;
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<int>used(nums.size(),0);
backtrack(nums,used);
return res;
}
};
2.元素不重复,可以无限制取
例题:leetcode 39.组合总和
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
class Solution {
public:
int sum=0;
vector<vector<int>>ans;
vector<int>path;
//无重复元素数组,无限制重复取
void backtrack(vector<int>& candidates, int target,int startindex){
if(sum==target){
ans.push_back(path);
return ;
}
if(sum>target){
return;
}
for(int i=startindex;i<candidates.size();i++){
sum+=candidates[i];
path.push_back(candidates[i]);
backtrack(candidates,target,i);///从自身位置开始
sum-=candidates[i];
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtrack(candidates,target,0);
vector<bool>used(candidates.size());
return ans;
}
};