代码随想录算法训练营第二十九天 | 回溯算法总结

news2024/11/18 5:34:33

代码随想录算法训练营第二十九天 | 回溯算法总结

1. 组合问题

1.1 组合问题

在77. 组合中,我们开始用回溯法解决第一道题目:组合问题。

回溯算法跟k层for循环同样是暴力解法,为什么用回溯呢?回溯法的魅力,用递归控制for循环嵌套的数量!

把回溯问题抽象为树形结构,如图:

在这里插入图片描述

可以直观的看出其搜索的过程:for循环横向遍历,递归纵向遍历,回溯不断调整结果集。

优化回溯算法只有剪枝一种方法,树形结构如图:

在这里插入图片描述

剪枝精髓是:for循环在寻找起点的时候要有一个范围,如果这个起点到集合终止之间的元素已经不够题目要求的k个元素了,就没有必要搜索了。

在for循环上做剪枝操作是回溯法剪枝的常见套路! 后面的题目还会经常用到。

1.2 组合总和

组合总和(一)

在216. 组合总和 III中,相当于在77. 组合加了一个元素总和的限制。

树形结构如图:

在这里插入图片描述

整体思路还是一样的,本题的剪枝会好想一些,即:已选元素总和如果已经大于n(题中要求的和)了,那么往后遍历就没有意义了,直接剪掉,如图:

在这里插入图片描述

在本题中,依然还可以有一个剪枝,就是77. 组合剪枝中提到的,对for循环选择的起始范围的剪枝。所以剪枝的代码可以在for循环加上 i <= 9 - (k - path.size()) + 1的限制!

组和总和(二)

在39. 组合总和中讲解的组合总和问题,和77.组合与216.组合总和III的区别是:本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。

本题还需要startIndex来控制for循环的起始位置,对于组合问题,什么时候需要startIndex呢?

如果是一个集合来求组合的话,就需要startIndex,例如:​77.组合与216.组合总和III
如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,例如:17. 电话号码的字母组合
以上我只是说求组合的情况,如果是排列问题,又是另一套分析的套路。​

树形结构如下:

在这里插入图片描述
本题的剪枝优化,如下:

for (int i = idx; i < candidates.length; i++) {
            // 如果 sum + candidates[i] > target 就终止遍历
            if (sum + candidates[i] > target) break;

优化后树形结构如下:
在这里插入图片描述

组合总和(三)

在组合总和II中集合元素会有重复,但要求解集不能包含重复的组合。
所以难就难在去重问题上了。
为了讲解这个去重问题,科普两个概:“树枝去重”和“树层去重”。

“树枝去重”和“树层去重”出自代码随想录Carl

都知道组合问题可以抽象为树形结构,那么“使用过”在这个树形结构上是有两个维度的,一个维度是同一树枝上“使用过”,一个维度是同一树层上“使用过”。没有理解这两个层面上的“使用过” 是造成大家没有彻底理解去重的根本原因。

在这里插入图片描述

我在图中将used的变化用橘黄色标注上,可以看出在candidates[i] == candidates[i - 1]相同的情况下:

  • used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
  • used[i - 1] == false,说明同一树层candidates[i - 1]使用过

对于去重,其实排列和子集问题也是一样的道理。

1.3 多个集合求组合

在17.电话号码的字母组合中,开始用多个集合来求组合,还是熟悉的模板题目,但是有一些细节。
例如这里for循环,可不像是在​77.组合与216.组合总和III中从startIndex开始遍历的。
因为本题每一个数字代表的是不同集合,也就是求不同集合之间的组合,而​77.组合与216.组合总和III都是是求同一个集合中的组合!

树形结构如下:
在这里插入图片描述

1.4 切割问题

在131.分割回文串中,我们开始讲解切割问题,虽然最后代码看起来好像是一道模板题,但是从分析到学会套用这个模板,是比较难的。

以下是几个难点:

  • 切割问题其实类似组合问题
  • 如何模拟那些切割线
  • 切割问题中递归如何终止
  • 在递归循环中如何截取子串
  • 如何判断回文

如果想到了用求解组合问题的思路来解决切割问题本题就成功一大半了,接下来就可以对着模板照葫芦画瓢。
后续如何模拟切割线,如何终止,如何截取子串,其实都不好想,最后判断回文算是最简单的了。
除了这些难点,本题还有细节,例如:切割过的地方不能重复切割所以递归函数需要传入i + 1。

树形结构如下:
在这里插入图片描述

子集问题

子集问题(一)

在78. 子集中讲解了子集问题,在树形结构中子集问题是要收集所有节点的结果,而组合问题是收集叶子节点的结果。

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

认清这个本质之后,今天的题目就是一道模板题了。

本题其实可以不需要加终止条件,因为startIndex >= nums.size(),本层for循环本来也结束了,本来我们就要遍历整棵树。
不写终止条件会不会无限递归呢?
并不会,因为每次递归的下一层就是从i+1开始的。
如果要写终止条件,注意:result.add(new ArrayList<>(path));要放在终止条件的上面,如下:

result.add(new ArrayList<>(path));//「遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合」。
        if (startIndex >= nums.length){ //终止条件可不加
            return;
        }
子集问题(二)

在90.子集II中,开始针对子集问题进行去重。
本题就是78. 子集的基础上加上了去重,去重我们在组合总和II也讲过了,一样的套路。

树形结构如下:
在这里插入图片描述

递增子序列

在491.递增子序列中,处处都能看到子集的身影,但处处是陷阱,值得好好琢磨琢磨!

树形结构如下:
在这里插入图片描述
很多同学都会把这道题目和90.子集II混在一起。

2. 排列问题

排列问题(一)

46. 全排列又不一样了。

排列是有序的,也就是说 [1,2] 和 [2,1] 是两个集合,这和之前分析的子集以及组合所不同的地方。
可以看出元素1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了。

如图:
在这里插入图片描述
大家此时可以感受出排列问题的不同:

  • 每层都是从0开始搜索而不是startIndex
  • 需要used数组记录path里都放了哪些元素了
排列问题(二)

排列问题也要去重了,在47. 全排列 II中又一次强调了“树层去重”和“树枝去重”。

树形结构如下:
在这里插入图片描述
这道题目神奇的地方就是used[i - 1] = = false也可以,used[i - 1] = = true也可以!

本题used数组即是记录path里都放了哪些元素,同时也用来去重,一举两得。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1118427.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

excel常用的几个函数

1、MID函数 通常用来返回返回指定字符串中的子串。 函数公式&#xff1a; MID(string, starting_at, extract_length) String&#xff08;必填&#xff09;&#xff1a;包含要提取字符的文本字符串 starting_at&#xff08;必填&#xff09;&#xff1a;文本中要提取的第一个字…

Tomcat及jdk安装下载及环境配置(超超超详解)

我是看了两篇博客安装配置好的 jdk 最详细jdk安装以及配置环境&#xff08;保姆级教程&#xff09;_安装jdk需要配置环境变量吗-CSDN博客 tomcat Tomcat的下载安装与配置及常见问题处理【Win11】 - 鞠雨童 - 博客园 (cnblogs.com) 本篇文章是我解决了很多朋友的tomcat配置问题总…

基于RIP的MGRE实验

题目及视图&#xff1a; 实验要求&#xff1a; 1.R5为ISP&#xff0c;只能进行IP地址配置&#xff0c;其所有地址均配为公有IP地址 2.R1和R5间使用PPP的PAP认证&#xff0c;R5为主认证 R2与R5之间使用ppp的CHAP认证&#xff0c;R5为主认证方 R3与R5之间使用HDLC封装 3.R1…

【C++学习笔记】引用

1. 概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空 间&#xff0c;它和它引用的变量共用同一块内存空间。 比如&#xff1a;孙悟空&#xff0c;有人叫弼马温&#xff0c;也有人称为齐天大圣。 1.1 使用方…

计算机毕业设计 基于SpringBoot智慧养老中心管理系统的设计与实现 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

粤嵌实训医疗项目--day01(Vue+SpringBoot)

目录 一、创建工作空间及配置Maven环境 二、创建springboot项目整合web操作 三、http请求参数获取及登录页面访问操作 四、数据库设计、数据库创建及导入sql 五、使用mybatis-plus逆向工程生成代码【vaccinum】 六、JavaEE三层架构概念及user查询实现 七、mybatis-plus逆…

安装与脏数据绕过_安全狗

1安全狗 1.1 环境准备 安全狗safedogwzApacheV3.5.exe&#xff0c;安装步骤省略&#xff0c; pikachu环境&#xff1a;https://zhuanlan.zhihu.com/p/568493971 安装注意事项&#xff1a;安装完后php和web服务都需要重启 注意事项&#xff1a;服务名php版本保持一致 安装过…

UG\NX二次开发 获取调色板CDF文件的内容

文章作者:里海 来源网站:《里海NX二次开发3000例专栏》 感谢粉丝订阅 感谢 迈克尔.卓别煷 订阅本专栏,非常感谢。 简介 UG\NX二次开发 获取调色板CDF文件的内容 文件->首选项->调色板 效果 代码 #include "me.hpp" #

使用Simple JWT提供认证服务(详细介绍access_token和refresh_token的使用)

文章目录 基本概念JSON Web Token&#xff08;JWT&#xff09;Simple JWT 主要用途Cookie、Session、Token的区别CookieSessionToken Token续签access_token 和 refresh_token时效设置 基本概念 JSON Web Token&#xff08;JWT&#xff09; JSON Web Token&#xff08;JWT&am…

探索大数据时代的关键技术:数据挖掘、可视化和数据仓库

文章目录 &#x1f31f; 大数据和数据分析技术&#x1f34a; 引言&#x1f34a; 数据挖掘&#x1f34a; 数据可视化&#x1f34a; 数据仓库&#x1f34a; 结论 &#x1f4d5;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里…

【Linux基础】详谈Shell运行原理------王婆传媒(高重复率面试题)

目录 &#x1f4a7;前言 &#x1f4a6;Shell的运行原理 &#x1f449;Shell的基本概念与作用 &#x1f449;原理的展示与剖析 &#x1f449;Shell外壳感性理解【一门亲事】 &#x1f4a7;总结 &#x1f4a7;共勉 &#x1f4a7;前言 在之前的 Linux 讲解中&#xff0c;主要说…

【管理运筹学】第 10 章 | 排队论(2,到达时间间隔的分布和服务时间的分布)

文章目录 引言一、普阿松分布二、负指数分布三、爱尔朗分布 引言 解决排队问题&#xff0c;首先要根据原始资料做出顾客到达时间间隔和服务时间的经验分布&#xff0c;然后按照统计学的方法&#xff08;如 χ 2 \chi^2 χ2 检验&#xff09;以确定属于哪种分布理论&#xff0…

JS数组方法合集(含应用场景)

1.Array.push() 向数组的末尾添加一个或多个元素&#xff0c;并返回新的数组长度。原数组改变 const arr ["apple", "orange", "grape"]; const arr_length arr.push("banana");console.log("arr", arr, "arr_leng…

JOSEF约瑟 JHOK-ZBM1;JHOK-ZBL1多档切换式漏电(剩余)继电器 面板导轨安装

系列型号&#xff1a; JHOK-ZBL多档切换式漏电&#xff08;剩余&#xff09;继电器&#xff08;导轨&#xff09; JHOK-ZBL1多档切换式漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBL2多档切换式漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBM多档切换式漏电&#xf…

【算法训练-动态规划 一】【应用DP问题】零钱兑换、爬楼梯、买卖股票的最佳时机I、打家劫舍

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【动态规划】&#xff0c;使用【数组】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…

springBoot--web--favicon规则

在静态资源目录中找favicon.icon 推荐图标工具 favicon使用 在静态资源中放入下载好的图片,改名为favicon.ico

互联网医院|互联网医疗模式已从概念走向实体建设阶段

近年来&#xff0c;医疗服务领域新形态不断涌现&#xff0c;“互联网医疗”作为其中突出的一种&#xff0c;在挂号结算、远程诊疗、咨询服务等方面进行了不少探索&#xff0c;而早在2015年全国互联网医院成立&#xff0c;标志着“互联网医疗”模式已经从概念走向了实体建设阶段…

【Arduino TFT】Arduino uzlib库,用于解压gzip流,解析和风天气返回数据

忘记过去&#xff0c;超越自己 ❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-10-21 ❤️❤️ 本篇更新记录 2023-10-21 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &#x1f44d;收藏 ⭐️留言&#x1f4dd;&#x1f64…

开源WAF--Safeline(雷池)测试手册

长亭科技—雷池(SafeLine)社区版 官方网站:长亭雷池 WAF 社区版 (chaitin.cn) WAF 工作在应用层&#xff0c;对基于 HTTP/HTTPS 协议的 Web 系统有着更好的防护效果&#xff0c;使其免于受到黑客的攻击 1.1 雷池的搭建 1.1.1 配置需求 操作系统&#xff1a;Linux 指令架构&am…