Example 1:
Input: n = 4, k = 2
Output: [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
Explanation: There are 4 choose 2 = 6 total combinations.
Note that combinations are unordered, i.e., [1,2] and [2,1] are considered to be the same combination.
Example 2:
Input: n = 1, k = 1
Output: [[1]]
Explanation: There is 1 choose 1 = 1 total combination.
Constraints:
1 <= n <= 201 <= k <= n
Carl 提供的回溯模板很有用,以前递归也能写但没做过这样的总结。 模板
void backtracking(参数) { if (终止条件) { 存放结果; return; }
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
组合是标准递归问题,每层递归处理一个长度的组合,用for循环call遍余下的元素。递归由上到下,按数组顺序来选元素。用一个startIndex来标记本层的起始元素位置。 选满k个元素,就把当前选过的元素集合加到结果集里。 剪枝操作,就是在当前循环中,如果剩下的元素不足以填满k,就没必要继续遍历。
class Solution {
public void backtracking(List<Integer> path, int n, int k, int start, List<List<Integer>> res) {
if(path.size() == k) {
res.add(new ArrayList<>(path));
//System.out.println(path.toString());
return;
}
for(int i=start; i<=n - (k-path.size()) + 1; i++) {
path.add(i);
backtracking(path, n, k, i+1, res);
path.remove(path.size() - 1);
}
}
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
List<Integer> path = new ArrayList<Integer>();
backtracking(path, n, k, 1, res);
return res;
}
}