题目:
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.
Ensure that numbers within the set are sorted in ascending order.
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]]
题解:
Combination Sum 3,求和为n的k位组合数,输入number只有{1, 2, 3, 4, 5, 6, 7, 8, 9}并且无重复。 首先的想法是dfs + backtracking,不用花很多时间就可以写出来。
Time Complexity - O(29), Space Complexity - O(n)
public class Solution { public List<List<Integer>> combinationSum3(int k, int n) { List<List<Integer>> res = new ArrayList<>(); List<Integer> list = new ArrayList<>(); combinationSum3(res, list, k, n, 1); return res; } private void combinationSum3(List<List<Integer>> res, List<Integer> list, int k, int n, int pos) { if(n < 0 || k < 0) return; if(n == 0 && k == 0){ res.add(new ArrayList<Integer>(list)); return; } for(int i = pos; i <= 9; i++) { list.add(i); combinationSum3(res, list, k - 1, n - i, i + 1); list.remove(list.size() - 1); } } }
还看到一个很好的写法,因为输入只有1 ~ 9,结果也只是1 ~ 9里k个数的组合那么我们可以暴力遍历所有的29个数。这里有个比较巧妙的地方就是我们只用找有k个1 bit的数字,然后再计算是否满足条件和为n。(原理我也没想明白,数学不好...)
这样下来Time Complexity 依然是O(29), Space Complexity - O(n), 不过可以节省掉递归栈的开销。
二刷:
方法跟一刷基本一样。
Java:
Time Complexity - O(29), Space Complexity - O(n)
public class Solution { public List<List<Integer>> combinationSum3(int k, int n) { List<List<Integer>> res = new ArrayList<>(); combinationSum3(res, new ArrayList<>(), k, n, 1); return res; } private void combinationSum3(List<List<Integer>> res, List<Integer> list, int k, int n, int pos) { if (list.size() == k) { if (n == 0) res.add(new ArrayList<>(list)); return; } for (int i = pos; i <= 9; i++) { if (i > n) break; list.add(i); combinationSum3(res, list, k, n - i, i + 1); list.remove(list.size() - 1); } } }
三刷:
Java:
public class Solution { public List<List<Integer>> combinationSum3(int k, int n) { List<List<Integer>> res = new ArrayList<>(); combinationSum3(res, new ArrayList<>(), k, n, 1); return res; } private void combinationSum3(List<List<Integer>> res, List<Integer> list, int k, int n, int pos) {if (k == 0) { if (n == 0) res.add(new ArrayList<>(list)); return; } for (int i = pos; i <= 9; i++) { if (i > n) return; list.add(i); combinationSum3(res, list, k - 1, n - i, i + 1); list.remove(list.size() - 1); } } }
Reference:
https://leetcode.com/discuss/37036/my-java-solution-basic-recursion-with-backtracking
https://leetcode.com/discuss/37809/accepted-recursive-java-solution-easy-to-understand
https://leetcode.com/discuss/37077/just-iterate-all-combinations-of-c-n-k-no-dfs
https://leetcode.com/discuss/7181/what-time-complexity-recursive-solution-this-problem-how-get