本文 https://github.com/youngyangyang04/leetcode-master 已经收录,里面还有leetcode刷题攻略、各个类型经典题目刷题顺序、思维导图,可以fork到自己仓库,有空看一看一定会有所收获,如果对你有帮助也给一个star支持一下吧!

周一

在回溯算法:求组合总和(二)中讲解的组合总和问题,和以前的组合问题还都不一样。

本题和回溯算法:求组合问题!,回溯算法:求组合总和!和区别是:本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。

不少录友都是看到可以重复选择,就义无反顾的把startIndex去掉了。

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

我举过例子,如果是一个集合来求组合的话,就需要startIndex,例如:回溯算法:求组合问题!,回溯算法:求组合总和!。

如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,例如:回溯算法:电话号码的字母组合

注意以上我只是说求组合的情况,如果是排列问题,又是另一套分析的套路,后面我再讲解排列的时候就重点介绍

最后还给出了本题的剪枝优化,如下:

for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++)

这个优化如果是初学者的话并不容易想到。

在求和问题中,排序之后加剪枝是常见的套路!

在回溯算法:求组合总和(二)第一个树形结构没有画出startIndex的作用,这里这里纠正一下,准确的树形结构如图所示:

周二

在回溯算法:求组合总和(三)中依旧讲解组合总和问题,本题集合元素会有重复,但要求解集不能包含重复的组合。

所以难就难在去重问题上了

这个去重问题,相信做过的录友都知道有多么的晦涩难懂。网上的题解一般就说“去掉重复”,但说不清怎么个去重,代码一甩就完事了。

为了讲解这个去重问题,我自创了两个词汇,“树枝去重”和“树层去重”

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

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

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

这块去重的逻辑很抽象,网上搜的题解基本没有能讲清楚的,如果大家之前思考过这个问题或者刷过这道题目,看到这里一定会感觉通透了很多!

对于去重,其实排列问题也是一样的道理,后面我会讲到。

周三

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

我列出如下几个难点:

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

如果想到了用求解组合问题的思路来解决 切割问题本题就成功一大半了,接下来就可以对着模板照葫芦画瓢。

但后序如何模拟切割线,如何终止,如何截取子串,其实都不好想,最后判断回文算是最简单的了

除了这些难点,本题还有细节,例如:切割过的地方不能重复切割所以递归函数需要传入i + 1

所以本题应该是一个道hard题目了。

本题的树形结构中,和代码的逻辑有一个小出入,已经判断不是回文的子串就不会进入递归了,纠正如下:

周四

如果没有做过回溯算法:分割回文串的话,回溯算法:复原IP地址这道题目应该是比较难的。

复原IP照回溯算法:分割回文串就多了一些限制,例如只能分四段,而且还是更改字符串,插入逗点。

树形图如下:

在本文的树形结构图中,我已经把详细的分析思路都画了出来,相信大家看了之后一定会思路清晰不少!

本题还可以有一个剪枝,合法ip长度为12,如果s的长度超过了12就不是有效IP地址,直接返回!

代码如下:

if (s.size() > 12) return result; // 剪枝

我之前给出的C++代码没有加这个限制,也没有超时,因为在第四段超过长度之后,就会截止了,所以就算给出特别长的字符串,搜索的范围也是有限的(递归只会到第三层),及时就会返回了。

周五

在回溯算法:求子集问题!中讲解了子集问题,在树形结构中子集问题是要收集所有节点的结果,而组合问题是收集叶子节点的结果

如图:

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

其实可以不需要加终止条件,因为startIndex >= nums.size(),本层for循环本来也结束了,本来我们就要遍历整颗树。

有的同学可能担心不写终止条件会不会无限递归?

并不会,因为每次递归的下一层就是从i+1开始的。

如果要写终止条件,注意:result.push_back(path);要放在终止条件的上面,如下:

result.push_back(path); // 收集子集,要放在终止添加的上面,否则会漏掉自己
if (startIndex >= nums.size()) { // 终止条件可以不加return;
}

周六

早起的哈希表系列没有总结,所以哈希表:总结篇!(每逢总结必经典)如约而至。

可能之前大家做过很多哈希表的题目,但是没有串成线,总结篇来帮你串成线,捋顺哈希表的整个脉络。

大家对什么时候各种set与map比较疑惑,想深入了解红黑树,哈希之类的。

如果真的只是想清楚什么时候使用各种set与map,不用看那么多,把关于哈希表,你该了解这些!看了就够了

总结

本周我们依次介绍了组合问题,分割问题以及子集问题,子集问题还没有讲完,下周还会继续。

我讲解每一种问题,都会和其他问题作对比,做分析,所以只要跟着细心琢磨相信对回溯又有新的认识

最近这两天题目有点难度,刚刚开始学回溯算法的话,按照现在这个每天一题的速度来,确实有点快,学起来吃力非常正常,这些题目都是我当初学了好几个月才整明白的,哈哈。

所以大家能跟上的话,已经很优秀了!

还有一些录友会很关心leetcode上的耗时统计。

这个是很不准确的,相同的代码多提交几次,大家就知道怎么回事了。

leetcode上的计时应该是以4ms为单位,有的多提交几次,多个4ms就多击败50%,所以比较夸张,如果程序运行是几百ms的级别,可以看看leetcode上的耗时,因为它的误差10几ms对最终影响不大。

所以我的题解基本不会写击败百分之多少多少,没啥意义,时间复杂度分析清楚了就可以了,至于回溯算法不用分析时间复杂度了,都是一样的爆搜,就看谁剪枝厉害了。

一些录友表示最近回溯算法看的实在是有点懵,回溯算法确实是晦涩难懂,可能视频的话更直观一些,我最近应该会在B站(同名:「代码随想录」)出回溯算法的视频,大家也可以看视频在回顾一波。

就酱,又是充实的一周,做好本周总结,迎接下一周,冲!

我是程序员Carl,可以找我组队刷题,也可以在B站上找到我,本文leetcode刷题攻略已收录,更多精彩算法文章尽在公众号:代码随想录,关注后就会发现和「代码随想录」相见恨晚!

如果感觉对你有帮助,不要吝啬给一个

「leetcode」本周小结!(回溯算法系列二)相关推荐

  1. 「leetcode」最强回溯算法总结篇!历时21天、画了20张树形结构图、14道精选回溯题目精讲

    本文 https://github.com/youngyangyang04/leetcode-master 已经收录,里面还有leetcode刷题攻略.各个类型经典题目刷题顺序.思维导图,可以fork ...

  2. 八十四、Python | Leetcode回溯算法系列

    @Author:Runsen @Date:2020/7/7 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰 ...

  3. 【算法系列 二】Stack

    为什么80%的码农都做不了架构师?>>>    栈应用的场景: 1.括号问题 2.后缀表达式 3.深度优先遍历 4.保存现场 1. 给定字符串,仅由"()[]{}" ...

  4. 算法系列(二):贪心算法--Huffman编码

    算法系列(二):贪心算法--Huffman编码 一.分析 问题描述: 哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法.其压缩率通常在20%-90%之间.哈夫曼编码算法使用字符在文件中出现的频率 ...

  5. 「leetcode」332.重新安排行程【回溯算法/深搜】详细图解!

    本文 https://github.com/youngyangyang04/leetcode-master 已经收录,里面还有leetcode刷题攻略.各个类型经典题目刷题顺序.思维导图,可以fork ...

  6. js实现kmp算法_「leetcode」459.重复的子字符串:KMP算法还能干这个!

    不瞒你说,重复子串问题,KMP很拿手 题目459.重复的子字符串 给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成.给定的字符串只含有小写英文字母,并且长度不超过10000. 示例 1: ...

  7. 消除左递归c++代码_「leetcode」129. 求根到叶子节点数字之和【递归中隐藏着回溯】详解...

    链接 https://leetcode-cn.com/problems/sum-root-to-leaf-numbers/ 思路 本题和113.路径总和II是类似的思路,做完这道题,可以顺便把113. ...

  8. c++矩阵连乘的动态规划算法并输出_「Javascript算法设计」× 动态规划与回溯算法...

    目录: 分而治之算法 动态规划 回溯算法 分而治之算法 分而治之算法是算法设计的一种方式,它将一个问题分成多个和原问题相似的小问题,递归解决小问题,再将解决方式合并以解决原来的问题(例如快速排序,二分 ...

  9. 消除左递归实验代码_「leetcode」108. 构造二叉搜索树【递归】【迭代】详解!

    构造二叉搜索树,一不小心就平衡了 ❞ 108.将有序数组转换为二叉搜索树 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树 ...

  10. 二维数组删除_「leetcode」数组:总结篇!(一文搞懂数组题目)

    数组理论基础 数组是非常基础的数据结构,在面试中,考察数组的题目一般在思维上都不难,主要是考察对代码的掌控能力 也就是说,想法很简单,但实现起来 可能就不是那么回事了. 首先要知道数组在内存中的存储方 ...

最新文章

  1. 最佳DevOps工具获奖者:CloudBees Jenkins平台
  2. java 多种类型文件复制_java多种文件复制方式以及效率比较
  3. CSS的三种使用方式
  4. Java中List接口重要实现类一ArrayList
  5. html大学生活主题班会,“大学生活”主题班会记录范文
  6. (常用API)正则表达式的概念和作用
  7. powerdesigner显示工具面板_10分钟看懂Photoshop 绘画(画笔面板1-3)
  8. 将COleDateTime类型数据转换成char *数据
  9. 学习MySQL:使用SELECT语句从MySQL服务器查询数据
  10. [论文阅读] Cross-layer feature pyramid network for salient object detection
  11. ALinq 让Mysql变得如此简单
  12. node-js由浅入深教程
  13. 讨论oracle在rowid和rownum
  14. springboot 整合redis配置文件
  15. iconfont-阿里巴巴矢量图标库在layui中的使用
  16. 打印机扫描显示计算机故障或繁忙,打印机无法扫描_如何用打印机进行扫描,如何用打印机扫描文件...
  17. hdu-6638 Snowy Smile
  18. 在线富文本编辑器-基于Web的HTML编辑器大全(二)
  19. 如何通过三视图判断立方体个数_“三视图”“小正方体个数”一篇搞定!
  20. 多线程模拟龟兔赛跑游戏

热门文章

  1. vs2013使用remote debug
  2. Android自定义控件之TextView
  3. 根据元素相对位置来控制滚动条
  4. Java过滤emoji表情,找出emoji的unicode范围。
  5. Axure中继器设置单选
  6. 谷歌浏览器整个网页截图方法
  7. 读“让你的软件飞起来”持续更新代码运行效率之路
  8. codevs 1164 统计数字
  9. 我的树莓派3配置脚本
  10. eclipse svn设置忽略文件