leetcode 216. 组合总和 III 思考分析

138 阅读2分钟

可能需要回顾的文章;
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;
    }
};