组合
我们可以对该题的递归进行剪枝,我们从大到小开始递归,如果递归到的数字小于要剩下递归的个数
那么说明当前递归的数不够就不要继续递归
class Solution {
private int k;
private final List<List<Integer>> ans = new ArrayList<>();
private final List<Integer> path = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
this.k = k;
dfs(n);
return ans;
}
private void dfs(int i) {
int d = k - path.size(); // 还要选 d 个数
if (d == 0) { // 选好了
ans.add(new ArrayList<>(path));
return;
}
for (int j = i; j >= d; j--) {
path.add(j);
dfs(j - 1);
path.remove(path.size() - 1); // 恢复现场
}
}
}
组合总和 III
这个题和上一题差不多,我们只需要在增加一个剪枝条件,就是target目标值是否小于零或者它大于剩下的要递归的数中从最大的数开始到剩下要递归的数的个数这几个数的值,就比如现在目标值是10,剩下的数是5,4,3,2,剩下要递归两个数,但是5+4小于10,所以后面的直接不进行递归
class Solution {
private List<List<Integer>> ans = new ArrayList<>();
private List<Integer> path;
int K;
public List<List<Integer>> combinationSum3(int k, int n) {
this.K = k;
path = new ArrayList<>(k);
f(9,n);
return ans;
}
public void f(int i,int target){
int d = K - path.size(); // 还要选 d 个数
if(target < 0 || target > ((i * 2 - d + 1) * d / 2)){
return;
}
if (d == 0) { // 选好了
ans.add(new ArrayList<>(path));
return;
}
for (int j = i; j >= d; j--) {
path.add(j);
f(j - 1,target-j);
path.remove(path.size() - 1); // 恢复现场
}
}
}
括号生成
这个题我们可以用选与不选的角度来写,先选择
(
,然后判断)
的个数是否大于(
的个数,如果不大于选择)
,然后递归
class Solution {
private List<String> ans = new ArrayList<String>();
private char[] path;
int N;
public List<String> generateParenthesis(int n) {
path = new char[n * 2];
this.N = n;
f(0,0);
return ans;
}
public void f(int i, int open) {
if(i == N * 2){
ans.add(String.valueOf(path));
}
if(open < N){
path[i] = '(';
f(i+1, open+1);
}
if(i - open < open){
path[i] = ')';
f(i+1, open);
}
}
}