注:图片借鉴代码随想录
组合问题
回溯法解决组合问题的最基础题型
我们把这个选k个数的流程用树来画出来:
我们可以看到,组合问题的特点就是对于1来说,取过1的分支已经在走了,则其他分支不需要考虑1了(和排列不同,排列的话在不同层的1是不一样的情况)。我们递归遍历时,下一层都从上一层的id+1开始取数。
void backtrack(int k,int n, int nowid, vector<vector<int>>& res, vector<int>& temp){
if(temp.size()==k){
res.push_back(temp);
return;
}
for(int i=nowid;i<=n;i++){
//相当于树中同层遍历
temp.push_back(i);
backtrack(k,n,i+1,res,temp); //向下递归
temp.pop_back();
}
}
组合问题2:当数组中有重复元素的时候,求所有组合情况的时候如何去重?
首先理解一下重复是怎么造成的 [10,1a,1b]
- 取1a–>不取1b
- 取1b
这两者是一样的
在dfs过程中,dfs(1a往后)一定cover了dfs(1b往后)的可能性,所以没有必要放1b.
我们要区分往下递归和横向遍历,
对于往下递归来说,可以有重复的1,它代表结果数组中可以出现重复的数如1,1,2 ,
对于横向遍历来说,虽然有1a和1b这两个1,但它们本质是一样的,同层放入同样数就是组合的重复,我们需要跳过这种情况。
注意:有同样数的情况,我们需要先排序,这样方便跳过。
void backtrack(vector<vector<int>>& res, vector<int>& temp,
vector<int>& candidates,int target,int nowSum,int id){
if(nowSum == target){
res.push_back(temp);
return;
}
for(int i=id;i<candidates.size();i++){
nowSum += candidates[i];
if(nowSum > target