给定两个整数 n
和 k
,返回范围 [1, n]
中所有可能的 k
个数的组合。
你可以按 任何顺序 返回答案。
示例 1:
1 2 3 4 5 6 7 8 9 10
| 输入:n = 4, k = 2 输出:
|
示例 2:
1 2
| 输入:n = 1, k = 1 输出:[[1]]
|
提示:
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Solution { List<List<Integer>> res = new ArrayList<>(); List<Integer> path = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) { traversal(n, k ,1); return res; }
public void traversal(int n, int k, int startIndex){ if(path.size() == k){ res.add(new ArrayList<>(path)); return; }
for(int i = startIndex; i <= n; i++){ path.add(i); traversal(n,k,i+1); path.remove(path.size()-1); } } }
|
- 时间复杂度: $O(n * 2^n)$,n为集合的大小,本题中n为9,每个数有两种状态,选或不选
- 空间复杂度: $O(n)$
剪枝优化
优化过程:
- 已经选择的元素个数:path.size();
- 还需要的元素个数为: k - path.size();
- 在集合n中至多只能从该起始位置 : n - (k - path.size()) + 1,开始回溯
比如:n=6,k-path.size() = 2, 最多只能从6-4+1=5开始回溯
for循环修改为
1
| for (int i = startIndex; i <= n - (k - path.size()) + 1; i++)
|
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Solution { List<List<Integer>> res = new ArrayList<>(); List<Integer> path = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) { traversal(n, k ,1); return res; }
public void traversal(int n, int k, int startIndex){ if(path.size() == k){ res.add(new ArrayList<>(path)); return; }
for(int i = startIndex; i <= n - (k-path.size()) + 1; i++){ path.add(i); traversal(n,k,i+1); path.remove(path.size()-1); } } }
|