首页 > 编程语言 >算法刷题 Day 24 | 回溯的理论基础 & 77. 组合

算法刷题 Day 24 | 回溯的理论基础 & 77. 组合

时间:2023-01-29 20:56:01浏览次数:65  
标签:24 剪枝 遍历 int 个数 77 算法 回溯 Day

今日内容:

  • 理论基础
  • 77. 组合

详细布置

理论基础

其实在讲解二叉树的时候,就给大家介绍过回溯,这次正式开启回溯算法,大家可以先看视频,对回溯算法有一个整体的了解。

题目链接/文章讲解:https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

视频讲解:https://www.bilibili.com/video/BV1cy4y167mM

77. 组合

对着 在 回溯算法理论基础 给出的 代码模板,来做本题组合问题,大家就会发现 写回溯算法套路。

在回溯算法解决实际问题的过程中,大家会有各种疑问,先看视频介绍,基本可以解决大家的疑惑。

本题关于剪枝操作是大家要理解的重点,因为后面很多回溯算法解决的题目,都是这个剪枝套路。

题目链接/文章讲解:https://programmercarl.com/0077.%E7%BB%84%E5%90%88.html

视频讲解:https://www.bilibili.com/video/BV1ti4y1L7cv

剪枝操作:https://www.bilibili.com/video/BV1wi4y157er

Tips:回溯和递归是一体两面的,要记住它的使用场景:

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

在代码中,遍历的范围是可以剪枝优化的,怎么优化呢?

来举一个例子,n = 4,k = 4的话,那么第一层for循环的时候,从元素2开始的遍历都没有意义了。 在第二层for循环,从元素3开始的遍历都没有意义了。

这么说有点抽象,如图所示:

77.组合4

图中每一个节点(图中为矩形),就代表本层的一个for循环,那么每一层的for循环从第二个数开始遍历的话,都没有意义,都是无效遍历。

所以,可以剪枝的地方就在递归中每一层的for循环所选择的起始位置

如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了

注意代码中i,就是for循环里选择的起始位置。

for (int i = startIndex; i <= n; i++) {

接下来看一下优化过程如下:

  1. 已经选择的元素个数:path.size();

  2. 还需要的元素个数为: k - path.size();

  3. 在集合n中至多要从该起始位置 : n - (k - path.size()) + 1,开始遍历

为什么有个+1呢,因为包括起始位置,我们要是一个左闭的集合。

举个例子,n = 4,k = 3, 目前已经选取的元素为0(path.size为0),n - (k - 0) + 1 即 4 - ( 3 - 0) + 1 = 2。

从2开始搜索都是合理的,可以是组合[2, 3, 4]。

这里大家想不懂的话,建议也举一个例子,就知道是不是要+1了。

所以优化之后的for循环是:

for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) // i为本次搜索的起始位置

我的题解:

class Solution {
public:
    vector<vector<int>> result;
    vector<int> temp;
    void backtracking(int n, int k, int begin){
        if(temp.size() == k){
            result.push_back(temp);
            return;
        }

        // 这里进行了剪枝操作
        for(int i = begin;i <= n - (k - temp.size()) + 1;i++){
            temp.push_back(i);
            backtracking(n,k,i+1);
            temp.pop_back();
        }
        return;
    }
    vector<vector<int>> combine(int n, int k) {
        backtracking(n, k, 1);
        return result;
    }
};

标签:24,剪枝,遍历,int,个数,77,算法,回溯,Day
From: https://www.cnblogs.com/GavinGYM/p/17073794.html

相关文章

  • Linux学习-DAY5
    一、文件目录管理命令1.touch命令touch命令用于创建空白文件或设置文件的时间,语法格式为“touch[参数] 文件名称”。2.mkdir命令mkdir命令用于创建空白的目录,英文全称为“......
  • Allen vue项目课day1_vue基础
    html讲义css讲义js讲义vue讲义去学。其他什么也不用管。就是脚踏实地,知识一个一个学。怎么挣到钱=怎么学会技术=怎么把成绩学好=怎么把一个又一个题目做出来。脚踏实......
  • Day1---注释
    注释分为:1、单行注释://内容publicclassHello{publicstasticvoidmain(String[]args){System.out.println("HelloWorld!");//这是单行注释,不会打印出来}}......
  • 算法刷题 Day 23 | 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二
    今日内容:修剪二叉搜索树将有序数组转换为二叉搜索树把二叉搜索树转换为累加树总结篇详细布置669.修剪二叉搜索树这道题目比较难,比添加增加和删除......
  • WebAPI_DAY1
    WebAPI作用:使用JS去操作html和浏览器分类:DOM(文档对象类型)、BOM(浏览器对象类型)DOM(DocumentObjectModel)浏览器提供的一套专门用来操作网页内容的功能开发网页特效、......
  • C++ Day10 统计圣经文本的词频 &文本查询程序
    一、编程题--统计圣经出现的单词以及词频统计一篇英文(The_Holy_Bible.txt)文章中出现的单词和词频,输入:某篇文章的绝对路径;输出:词典(词典中的内容为每一行都是一个“单词......
  • k8s v1.24.1 配置 cephfs
    本地环境情况角色IP版本k8s-master-1172.16.16.108K8Sv1.24.1,containerd://1.6.8k8s-node-1172.16.16.109K8Sv1.24.1,containerd://1.6.8k8s-no......
  • 【算法训练营day29】LeetCode491. 递增子序列 LeetCode46. 全排列 LeetCode47. 全排列
    LeetCode491.递增子序列题目链接:491.递增子序列独上高楼,望尽天涯难点在于如何在无法排序的情况下去重,核心思路是同层中同一父节点下使用过的元素就不能再使用了。cla......
  • day65 -查询完
    拆表查询查询父子信息,将一张表拆成两张看待进行查询--查询父子信息:把一张表拆成两张表SELECTa.`categoryname`AS'父栏目',b.`categoryname`AS'子栏目'FROM`......
  • 代码随想录算法训练营day14 | leetcode 层序遍历 226.翻转二叉树 101.对称二叉树 2
    层序遍历/***二叉树的层序遍历*/classQueueTraverse{/***存放一层一层的数据*/publicList<List<Integer>>resList=newArrayList<>()......