给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
示例 1:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | 输入:n = 4, k = 2输出:
 
 
 
 
 
 
 
 
 
 | 
示例 2:
| 12
 
 | 输入:n = 1, k = 1输出:[[1]]
 
 | 
提示:
 
代码
| 12
 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++) 
 | 
代码
| 12
 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);
 }
 }
 }
 
 |