找出所有相加之和为?n
?的?k
?个数的组合,且满足下列条件:
返回?所有可能的有效组合的列表?。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
解释: 1 + 2 + 4 = 7 没有其他符合的组合了。
示例 2:
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
解释: 1 + 2 + 6 = 9 1 + 3 + 5 = 9 2 + 3 + 4 = 9 没有其他符合的组合了。
示例 3:
输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。 在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。
提示:
2 <= k <= 9
1 <= n <= 60
? ? ? ? 由题目概述可以知道就是把1-9不重复地排列目标个数并且和与目标值相同,因此我们可以想到用回溯法,即循环+递归:
? ? ? ? for(循环遍历1-9){
? ? ? ? ? ? ? ? 将遍历到的数放入数组
? ? ? ? ? ? ? ? dfs()递归进行下一次循环
? ? ? ? ? ? ? ? 递归回来后除去该数组元素,防止后续循环使数组长度一直增加的情况,保证该循环内的数组长度保持一致。
????????}
????????往复该操作直至数组元素个数与目标元素个数相符
? ? ? ? 判断是否与目标值相同,相同,则放入存放数组的数组中。
? ? ? ? 注:每次操作都需要跳过之前数组已放入的值,避免重复,即剪枝
图示(示例 2):
????????
class Solution {
//建立一个局部变量数组来存放数组
List<List<Integer>> list=new ArrayList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
//创建数组
List<Integer> l=new ArrayList<>();
//进入回溯
dfs(n,l,k,1);
return list;
}
public void dfs(int n,List<Integer> l,int k,int m){
if(k==0){
if(n!=0) return;
list.add(new ArrayList(l));
return;
}
//for循环遍历1-9
for(int x=m;x<=9;x++){
//若x>n则说明数组和大于目标值没必要再往后遍历,直接结束
if(x>n) break;
l.add(x);
//进入下一次递归,目标值-x
dfs(n-x,l,k-1,x+1);
//去除元素,才能实现后续循环的操作
l.remove(l.size()-1);
}
}
}
?