216.组合总数Ⅲ

组合总数Ⅲ

题目

找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。

说明:

所有数字都是正整数。
解集不能包含重复的组合。
示例 1:

输入: k = 3, n = 7
输出: [[1,2,4]]
示例 2:

输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的思路

这道题的本质还是枚举,从1-9中找出k个数满足和为n,所以采用回溯法。
把问题抽象成树

image

k相当于是树的深度,9相当于是宽度。
初步思路就是:
1.递归到叶子结点,叶子节点的用path.size() == k来确定。
2.判断是否满足sum=n,满足保存节点到结果集
3.回溯到上一个节点

题解

递归函数的返回值以及参数
随着选择数的增加,可选的数减少,就需要一个变量去标识每层递归的可选区间。设置startIndex作为标志变量,每一次递归startIndex都要少1,startIndex
参数中肯定需要k,来控制是否到达叶子节点
n表示目标和
参数sum表示path里元素的总和

List <List<Integer>> res = new ArrayList<> ();
List<Integer> path = new  ArrayList<> (); //符合条件的单一条件
void backtracking(int n,int k,int sum,int startIndex)

递归的终止条件
分两种情况
1.到达了叶子节点path.size()==k
2.当前的sum已经大于n了,说明后面不用继续开始取值了,从这里开始剪枝

if(sum>n){
	return;
}
if(path.size() == k){
//表示进入叶子节点了,取数=3了
	if(n-sum==0)
		res.add(new  ArrayList<> (path));
	return;
}

单层递归逻辑
通过每一次递归中嵌套一个for循环来达到多层循环的目的。每一次循环是从startIndex开始,循环中i表示本次循环的取值。
递归是从根节点往叶节点纵向遍历树,for循环时从左往右横向遍历树

for(int i=startIndex;i<=9;i++){
path.add(i);
backtracking(n,k,sum+i,i+1);
/*递归,回溯回去sum也会跟着变,所以这里sum作为参数传播
相当于sum +=i
backtracking(n,k,sum,i+1);
sum-=i
*/
path.remove(path.size()-1);

题解

class Solution {
    List <List<Integer>> res = new ArrayList<> ();
    List<Integer> path = new  ArrayList<> ();
    public List<List<Integer>> combinationSum3(int k, int n) {
        backtracking(n,k,0,1);
        return res;
    }
    void backtracking(int n,int k,int sum ,int startIndex){
        if(sum>n){
            return;
        }
        if(path.size() == k){
	        if(n-sum==0)
		        res.add(new  ArrayList<> (path));
        	return;
        }
		//范围是[startIndex,9]
        for(int i=startIndex;i<=9;i++){
            path.add(i);
            backtracking(n,k,sum+i,i+1);
            path.remove(path.size()-1);
        }
    }
}
posted @ 2021-05-26 15:25  rananie  阅读(36)  评论(0编辑  收藏  举报