77.组合
文章
思路
回溯
两个全局变量,一个维护当前正在搜索的组合,另一个保存搜索到的满足要求的组合
每次进入下一层搜索,搜索的区间左侧收缩,右侧保持不变,剩余待搜索元素个数减1
最底层应当是
C
r
i
g
h
t
−
l
e
f
t
+
1
0
C^0_{right - left + 1}
Cright−left+10对应的k为0 的状态,此时combination长度满足要求,可以放入保存的结果中,此时需要删除combination末尾元素再返回上一层
考虑一种可以剪枝的情况,当区间长度恰好为待搜索元素个数时,可以直接将全部元素追加到combination末尾,保存满足要求的组合,然后删除这一段后返回。
代码
class Solution {
private List<Integer> combination;
private List<List<Integer>> combinations;
public List<List<Integer>> combine(int n, int k) {
combination = new ArrayList<>();
combinations = new ArrayList<>();
dfs(1, n, k);
return combinations;
}
public void dfs(int left, int right, int k) {
int i = left;
if (right - left == k - 1) {
while (i < right + 1) {
combination.add(i);
++i;
}
combinations.add(new ArrayList<>(combination));
while (i > left) {
combination.remove(combination.size() - 1);
--i;
}
return;
}
if (k == 0) {
combinations.add(new ArrayList<>(combination));
return;
}
while (right - i >= k - 1 && k > 0) {
combination.add(i);
dfs(i + 1, right, k - 1);
combination.remove(combination.size() - 1);
++i;
}
}
}
总结
今天犯过2个错误:
1)没有限制k非负,导致一直递归,栈溢出
2)向下层递归的条件没写等号,导致
l
e
f
t
=
=
r
i
g
h
t
left== right
left==right 时不向下搜索,总是漏解