可能需要回顾的文章;
leetcode 77. 组合 思考分析
1、题目
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
说明:
所有数字都是正整数。
解集不能包含重复的组合。
2、递归
这一题和之前一题很像:
leetcode 77. 组合 思考分析
终止条件有两个:sum==n && res.size() == k
回溯的过程中加入对sum值的修改。
修改一下递归函数的参数值,这样,本题就做好了
class Solution {
public:vector<vector<int>> result;vector<int> res;int sum;void clear_solution_param(){result.clear();res.clear();sum=0;}void backtracking(int start,int end,int k,int n){//找到了k个数if(res.size() == k && sum == n){result.push_back(res);return;}for(int i=start;i<=end;i++){//处理结点;res.push_back(i);sum+=i;//递归,探索下一层backtracking(i+1,end,k,n); //递归sum-=i;//回溯,撤销处理结果res.pop_back();}}vector<vector<int>> combinationSum3(int k, int n) {clear_solution_param();backtracking(1,9,k,n);return result;}
};
3、剪枝优化
1、我们之前的终止条件其实限的有问题,如果res.size已经等于k了,那么就没必要继续搜索了,直接返回。sum是否等于n只是关系到我们是否得到正确答案。所以应该修改为:
if(res.size() == k)
{if(sum == n) result.push_back(res);return; //如果size==k,但是sum!=n,直接返回
}
2、修改成上面那样其实还是有冗余,我们注意到,如果sum>n,此时也没有必要进行再次搜索了
if(sum>n) return;
if(res.size() == k)
{if(sum == n) result.push_back(res);return; //如果size==k,但是sum!=n,直接返回
}
3、同leetcode 77. 组合 思考分析的剪枝操作:
我们已经选择的元素个数为:res.size()
我们还需要的元素的个数为k-res.size()
所以最多从end-(k-res.size())+1的地方开始遍历。
for(int i=start;i<=end-(k-res.size())+1;i++)
{//处理结点;res.push_back(i);sum+=i;//递归,探索下一层backtracking(i+1,end,k,n); //递归sum-=i;//回溯,撤销处理结果res.pop_back();
}
4、最终代码:
class Solution {
public:vector<vector<int>> result;vector<int> res;int sum;void clear_solution_param(){result.clear();res.clear();sum=0;}void backtracking(int start,int end,int k,int n){if(sum>n) return;if(res.size() == k){if(sum == n) result.push_back(res);return; //如果size==k,但是sum!=n,直接返回}for(int i=start;i<=end-(k-res.size())+1;i++){//处理结点;res.push_back(i);sum+=i;//递归,探索下一层backtracking(i+1,end,k,n); //递归sum-=i;//回溯,撤销处理结果res.pop_back();}}vector<vector<int>> combinationSum3(int k, int n) {clear_solution_param();backtracking(1,9,k,n);return result;}
};