【力扣刷题|第十四天】回溯问题-组合型回溯

在这里插入图片描述

组合

力扣题目网址:组合

我们可以对该题的递归进行剪枝,我们从大到小开始递归,如果递归到的数字小于要剩下递归的个数
那么说明当前递归的数不够就不要继续递归

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

力扣题目网址:组合总和 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);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值