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,所以采用回溯法。
把问题抽象成树
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);
}
}
}