Question
Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.
Example 1:Input: k = 3, n = 7
Output:
[[1,2,4]]
Example 2:
Input: k = 3, n = 9
Output:
[[1,2,6], [1,3,5], [2,3,4]]
思路
因为k是不定的, 所以无法用LOOP(循环). 回溯法是此类题的常用解法. 注意要新建一个list 放入结果中, 否则放入的reference 会指向原来的不断变化的list,result.add(new ArrayList(cur));
代码
public class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
List<Integer> list = new ArrayList<Integer>();
if(k < 1 || k > 9 || n < 1 || n > 45)
return result;
generate(result,list,1,k,n);
return result;
}
public void generate(List<List<Integer>> result,List<Integer> list,int start,int k,int n){
//难点在于如何取得所有不重复的组合数
if(list.size() == k && n == 0){
result.add(new ArrayList(list));
return;
}
else if(list.size() >= k || n <= 0)
return;
for(int i = start;i <= 9;i++){
list.add(i);
generate(result,list,i + 1,k,n - i);
list.remove(list.size() - 1);
}
}
}
结果及分析
递归这种分析时间复杂度的就是看最后遍历的次数,回溯法难就难在不好理解遍历的顺序。此次遍历的顺序是:[1,2,3]->[1,2,4]->[1,2,5]->[1,2,6]->[1,2,7]->[1,2,8]->[1,2,9]->[1,3,4]->[1,3,5]…….
二刷
思路还是一样的,利用回溯法和dfs,code更简单了一点。
CODE
public class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> res = new ArrayList<>();
if(k == 0 || n == 0)
return res;
List<Integer> temp = new ArrayList<>();
helper(res,temp,k,n,1);
return res;
}
public void helper(List<List<Integer>> res,List<Integer> temp,int k,int n,int num){
if(temp.size() == k && n == 0){
res.add(new ArrayList<>(temp));
return;
}
else if(temp.size() > k || n < 0)
return;
for(int i = num;i <= 9;i++){
if(i > n)
return;
temp.add(i);
n -= i;
helper(res,temp,k,n,i + 1);
n += i;
temp.remove(temp.size() - 1);
}
}
}