【代码训练营】day24 | 回溯算法 & 77.组合

文章详细介绍了Java中使用回溯算法解决组合问题的思路和模板,包括回溯的终止条件、单层递归逻辑、回溯操作,以及如何进行剪枝以提高效率。通过示例代码解释了LeetCode77题的组合问题,并强调了在回溯过程中正确处理路径集合的重要性。
摘要由CSDN通过智能技术生成

所用代码 java

回溯:是一种纯暴力的搜索,搜索所有的情况,效率并不高,有些问题没办法用for循环暴力求出,只能回溯

应用场景:

  1. 组合问题(无序) 1234 (12 13 14 22 23 24 33 34)
  2. 切割问题 - - - -
  3. 子集问题
  4. 排列问题(有序)
  5. 棋盘问题 (N皇后、解数独)

回溯比较难懂,但都可以抽象为一棵n叉树,树的宽度就是处理结点集合的大小(for),树的深度就是递归的深度(递归)

回溯模板:

void backtracking(参数){
    if(终止条件){
        收集结果,通常都是在叶子结点 ;
        return ;
    }
    for(集合元素集,遍历每一个元素){
        处理结点 ;
        递归函数 ;
        回溯操作,撤销处理结点的操作 ;
    }
}

组合 LeetCode 77

题目链接:组合 LeetCode 77 - 中等

思路

无。


回溯三部曲:

  1. 回溯函数参数返回值
  2. 确定终止条件
  3. 单层递归逻辑
class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> combine(int n, int k) {
        backtarcking(n, k, 1);
        return res;
    }

    public void backtarcking(int n, int k, int startIndex){
        // 回溯终止条件
        if (path.size() == k){
//            错误的写法,这种写法传的是path的引用地址,会跟随着递归一直变化
//            res.add(path);
            // 正确的写法应该是把path赋值到一个新的list中
            List<Integer> temp = new ArrayList<>(path);
            res.add(temp);
            return;
        }

        // 单层递归逻辑
        for (int i = startIndex; i <=  n; i++) {
            path.add(i);
            // 下一层起始的位置是i+1
            backtarcking(n, k, i+1);
            // 回溯,把最后加的值给剪掉
            path.remove(path.size()-1);
        }
    }
}

剪枝操作:

假如我们n=4,k=3,我们在搜索的时候就没必要i从3开始了,因为从3开始就只有两个数,同样的再往深度递归的时候也没必要搜索那么多一定不符合的条件。

  • n=4,k=3
  • 那么我们还需要 k - path.size()个数,假如path里面已经存了一个数,那么就还需要3 - 1 = 2 个数
  • 所以说我们至多能从 n - (k - path.size()) + 1下标开始,也就是我的下标应该从比这个数小的开始

剪枝关键代码:

for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) {
    path.add(i);
    // 下一层起始的位置是i+1
    backtarcking(n, k, i+1);
    // 回溯,把最后加的值给剪掉
    path.remove(path.size()-1);
}

总结

写回溯的是主要是单层的递归逻辑,以及回溯的操作,有时候有些步骤有点难相通,可以多打印日志来查看哪里有问题,然后画个图更容易了解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值