代码随想录刷题训练营DAY24|回溯part1

回溯法,一般可以解决如下几种问题:

● 组合问题:N个数里面按一定规则找出k个数的集合
● 切割问题:一个字符串按一定规则有几种切割方式
● 子集问题:一个N个数的集合里有多少符合条件的子集
● 排列问题:N个数按一定规则全排列,有几种排列方式
● 棋盘问题:N皇后,解数独等等

如何理解?

抽象为树形结构
在这里插入图片描述

void backtracking(参数) {
if (终止条件) {
    存放结果;
    return;
}

for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
    处理节点;
    backtracking(路径,选择列表); // 递归
    回溯,撤销处理结果
}
}

77.组合

在这里插入图片描述
在这里插入图片描述

如何理解这个树形结构?

for循环横向遍历,纵向是递归遍历。
树的每一层可以看作是一个递归,每一个非叶子结点横向是一个for循环遍历。
在每一层里,去循环操作数组里的取数。

横向遍历(for循环):在每一层的递归中,for循环用于遍历从startIndex开始到n结束的所有可能选项。每次循环尝试将一个新的数字加入到当前的组合path中。
纵向遍历(递归调用):当加入一个新的元素到path后,代码通过递归调用进入下一层,这相当于在树形结构中向下走一层,寻找下一个可以加入path的元素,直到达到组合的长度k。
非叶子节点:树形结构中的非叶子节点表示一个部分构建的组合。每一次递归调用都尝试向这个部分构建的组合中添加一个新的元素,这是通过for循环实现的。
叶子节点:当构建的组合长度达到k时,达到一个叶子节点,这个完整的组合被添加到结果列表result中。
回溯:在达到叶子节点后,回溯发生,即移除path的最后一个元素(通过removeLast()方法),返回到上一个非叶子节点,继续for循环的下一次迭代,寻找下一个可能的元素。

回溯三部曲

● 递归函数的返回值及参数
● 回溯函数终止条件
○ path的大小=k,就可以终止
● 单层搜索的过程
○ backtracking通过不断调用自己一直往深处遍历,总会遇到叶子节点,遇到叶子节点就要返回。
○ 撤销本次处理结果。
■ 我们得到了[1,2],需要再把2拿出来,放入3得到[1,3],同理也要把3拿出来4放进去,得到[1,4]。

class Solution {
    List<Integer> path=new ArrayList<>();
    List<List<Integer>> result=new ArrayList<>(); 
    public List<List<Integer>> combine(int n, int k) {
        backtracking(n, k,1);
        return result;

    }

    public void backtracking(int n,int k,int startIndex){
        //回溯终止条件
        if(path.size()==k){
            //result.add(new ArrayList<>(path));确保了每次向result添加的都是当前path的一个独立的副本,从而使得每个组合都能正确无误地保存下来,避免了因path后续修改导致的数据错误。
            result.add(new ArrayList<>(path));
            return;
        }
        //控制树的横向遍历
        for(int i=startIndex;i<=n;i++){
            path.add(i);
            //递归,控制树的纵向遍历,下一层搜索从i+1开始
            backtracking(n, k,i+1);
            //回溯,撤销处理的节点
            path.removeLast();
        }

    }
}

● 第一层递归:初始startIndex=1,path加入1,变为[1]。
○ 调用backtracking(4, 2, 2),即从2开始寻找剩下的数加入组合。
● 第二层递归:这里开始遍历i的值从2开始。
○ 当i=2,path加入2,变为[1, 2],满足条件(path.size() == k),将[1, 2]添加到result中,然后移除2,path回到[1]。
○ 当i=3,path加入3,变为[1, 3],同样满足条件,将[1, 3]添加到result中,然后移除3,path回到[1]。
○ 当i=4,path加入4,变为[1, 4],同样满足条件,将[1, 4]添加到result中,然后移除4,path回到[1]。
● 回到第一层递归:完成所有i=1时的递归,移除1,path变回[]。
● i=2的递归开始:此时从2开始重复上述过程,直到遍历完所有可能的组合。

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值