题意:
给两个数n,k,找出所有n个各不相同的数的和是k的组合。
分析:
其实关键就是搜索遍历,怎么遍历呢?可以这样:
1,2,3 1,2,4 1,2,5 ... 1,2,9
1,3,4 1,3,5 1,3,6 ... 1,3,9
...
我们知道,这是深度优先搜索,对于一个搜索层数可能性不确定,只知道搜索结束条件的搜索问题,我们考虑递归。
首先递归条件:一旦递归了k次(或list已经k个元素,递归就结束(不管结果如何))。结果也在这里放入(条件是和正好被减完),需要新构造一个list,否则添加的list是不定的。
其次是递归参数:我们需要传递总和和当前部分。(因为这两个是不断变化的)
最后是递归主体:对于当前划分的子部分而言,我们关注下一个子部分(下一层)可能是从当前部分+1到9.(通过循环)
注意:每次递归执行结束,就意味着这一个结点的下一层已经遍历完毕,回到了这个节点,或者是下一层不满足条件,回到了这个节点。但是接下来需要走到同一层的相邻结点,但是list,里面已经放入了本层的本节点,所以需要remove。否则就会出现连续加入同一层的节点的情况。
public class Solution {
List<List<Integer>> list = new ArrayList<>();
List<Integer> l = new ArrayList<>();
int k;
public List<List<Integer>> combinationSum3(int k, int n) {
this.k = k;
helper(n, 1);
return list;
}
private void helper(int sum, int sub){
if(l.size() == k){
if(sum == 0)
list.add(new ArrayList<Integer>(l)); //这里要主要新构造
return;
}
for(int i=sub; i<=9; i++){ //遍历本层结点
l.add(i); //装入本层当前结点
helper(sum-i, i+1); //从当前节点进入下一层
l.remove(l.size()-1); //从下一层返回了当前结点(为空或者已经遍历完),接下来要横向遍历本层相邻结点,所以需要先取出当前结点
}
}
}