文章目录

  • 一、什么是回溯算法?
  • 二、如何实现回溯算法呢?
  • 三、总结

一、什么是回溯算法?

回溯,也就是回退。举个例子,你从A地出发,要到B地去,但是从A地出发有多条路,在每条路上可能会遇到多条路口,回溯就是你先走其中一条路,比如路1,走完路1然后再回到A地,然后走路2,依次走剩下的路,直到走完所有的路。为了简单说明,只画了几个点辅助理解.

从A点出发时,前面有两条路,1号线和2号线,选择1号线出发,走完1号线所有的路再回来走2号线(当然,如果走1号线时满足了要求就不必回来了),选择1号线出发:

到达中间点M,而中间点M前面又有3条路线,也是先选择其中一条,之后再回来选择其他路线,这里选择3号线:

到达中间点X,中间点X前面只有一条路,不管前面是不是终点B都需要继续走下去了,好处是这里没有其他的路,只有一条,所以也不用选择了.

幸运的是到达了终点B,如果只要求到达终点B,那现在就完成任务了,但是这里要说的是回溯,肯定不会这么简单,如果问题是从A到B有几条路线,或者求出最短的一条路线(图中没有写出路线的长短),那就得都走一遍了.比如说计算从A到B有几条路线,那现在就需要从9号线往回走:

达到点X之后,9号线已经走过了,所以不能再走了,只能沿着3号线往回走.你可能会说3号线也走过了,怎么可以走3号线呢,这是因为9号线已经达到了死胡同,就是没有其他的路线了,而沿着3号线还可以继续走其他没有走过的路线,比如4号线\5号线.

沿着3号线往回走达到点M之后,面前有4条路线,1条是沿着1号线往回走,1条是走过的3号线,不能再走了,还有两条没有走过的4号线和5号线,选择其中一条走下去:

到达点Y,发现Y是个死活同,走不下去了,所以只能回去了.然后继续走5号线,按照刚才的走法,遇到不同的情况,选择不同的走法:

  • 1或多条没有走过的路线,选择其中1条走下去;
  • 走到终点\死胡同,就往回走;
  • 如果面前的路都走过了,那就再往回走.
    直到所有的路都走过一遍.

啰了吧嗦说了这么多,看着其实一点都不复杂,只要上过小学,这些应该都能看懂,主要是怎么实现(突然想起来我老师说的:“就是编程不行呗”)

二、如何实现回溯算法呢?

要想实现回溯算法,还需要说明几个事情(回溯三要素),1.你走过的路线–路径;2.你可以走的路线-选择列表;3.结束条件.

1.先说说路径,就是你已经走过了哪些地方,比如说让你计算从A到B最短路径,你现在在X点呢,那你得记住从A点到X点走了多远吧,但是只记住一个数值多远还不行,因为你之后还需要回退,还要减去3号线的距离,所以这里的路径应该是你走过路线的按顺序的集合,可以认为是一个数组,里面放着各个点;
2.其次就是选择列表,就是你需要知道接下来你可以往哪儿走啊,如果你从M点走过3号线,又回退到M点的时候,就不能再走3号线了,你怎么知道不能走了呢,你得记录一下哪个能走,哪个不能走啊(记录能走的即可).
3.最后就是结束条件了,当你走完所有的路线之后就是结束,如何知道结束呢,你得设置个条件啊,比如说在A点时,选择列表为空了,那就说明不能继续走下去了,就结束了.

这里举个例子:leetcode17题:电话号码的字母组合

class Solution {public:vector<string> letterCombinations(string digits) {}
};

这个题比上面的例子还要简单些,它的前后没有关系,前边AB点的例子,从A走后,后面的情况是受A影响的,而这里不影响,它都是固定的.比如输入234257,第一个就是2,第二个就是3,不存在第二个值受第一个值的影响,不过很多题目都是受影响的.回溯三要素:

  • 首先考虑路径,可以使用string的一个变量保存,遇到新的地点就添加,回退的时候就去掉string变量中最后的地点;
  • 然后是选择列表,完全可以将可选择的选项存到一个数组中,需要删除时,在数组中删掉,不过这样的消耗比较大,涉及数组的删除等,我们可以将开始的选择存储到列表,使用一个index索引指示哪些可以选择,比如index=2,则0-1就不能选择了,只有从2开始可以选择,并且是从小到大选择,否则的话就乱了套了.
  • 最后是结束条件,可以将选择完所有的string中的字符作为结束条件.

说一下解决回溯算法的套路吧,这是参考labuladong(微信公众号/网站/知乎)的框架(在这里十分感谢labuladong的硬核文章):

result = []
def backtrack(路径, 选择列表):if 满足结束条件:result.add(路径)returnfor 选择 in 选择列表:做选择backtrack(路径, 选择列表)撤销选择

开始我在做回溯算法题的时候一直有2个疑惑:选择1号线之后,再选择2号线时没有什么影响吗?怎么确定选择完1号线之后再选2号线呢?
关于第1个疑惑:其实是没有影响的,因为1号线在处理时,路径中会新增地点,而处理完之后,就会删除(这里就是回溯啦).所以当走完1号线,再走2号线的时候,路径还是只有起点A,因此不受影响;关于第二个问题,就是需要写个for循环,一次循环处理一次路线,整个for循环就是处理某个点之后的所有路线了.

说了这么多,最后的完整代码:

class Solution {public:vector<string> letterCombinations(string digits) {if( !digits.size() )return res;getLetter(digits,0);return res;}
private:void getLetter(string& digits, int index) {if( index<0 )return;if( index>=digits.size() ) {res.push_back(str);return;}int k=digits[index]-'2';for( int i=0; i<letter[k].size(); ++i ) {str+=letter[k][i];getLetter(digits,index+1);str.erase(str.end()-1);}}
public:vector<string> letter={"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};vector<string> res;string str="";
};

三、总结

上述我的解法不是最好的,但这是我想到的可以解决问题的解法,里面还可以有一些优化,之后可能还会继续研究.

其实回溯算法理解起来并不难,主要是实现的时候可能会比较绕,其实是刚开始接触的时候,越想越理解不了,我觉得看一下上述的框架,然后做几道题找找感觉,应该就没问题了.

参考文章:回溯算法详解_labuladong

数据结构与算法--回溯的理解以及实现相关推荐

  1. 数据结构与算法 / 回溯算法(八皇后、0 - 1 背包)

    回溯算法,顾名思义,就是在没有得到最优解的前提下,不断的返回至前面的岔路口位置,重新选择,直至遍历了所有的情况或者得到的预期最优解的情况下再结束. 与贪心算法不同的是,回溯算法理论上是可以得到最优解, ...

  2. 高级数据结构与算法 | 回溯算法(Back Tracking Method)

    文章目录 回溯 电话号码的字母组合 二进制手表 组合总数 全排列 活字印刷 N皇后 N皇后II 回溯 回溯是一种通过穷举所有可能情况来找到所有解的算法.如果一个候选解最后被发现并不是可行解,回溯算法会 ...

  3. 【数据结构与算法】深度理解队列(上)

    ✨hello,进来的小伙伴们,你们好耶!✨

  4. 【数据结构与算法】深入理解队列(下)

    ✨hello,进来的小伙伴们,你们好耶!✨

  5. 深入理解数据结构和算法

    hi,大家好,我是阿荣,今天分享一些对数据结构和算法精华总结,希望对大家的面试或者工作有一定的帮助: 看完本文可以学到什么 知道哪些数据结构和算法在实际工作中最常用,最重要 理解一些设计上注意事项(经 ...

  6. 【数据结构与算法】【算法思想】回溯算法

    贪心算法 回溯算法 分治算法 动态规划 回溯算法思想应用广泛,除了用来指导深度优先搜索这种经典算法设计之外,还可以用在如正则表达式匹配,编译原理中的语法分析等. 除此之外,很多经典的数学问题都可以用回 ...

  7. 数据结构与算法_04_回头是岸依好汉(回溯算法)

    数据结构与算法,系列文章传送地址,请点击本链接. 目录 一.怎么理解回溯算法 二.经典应用 1.0-1 背包问题 2.正则表达式 3.八皇后问题 一.怎么理解回溯算法 回溯算法的理解:回溯算法,顾名思 ...

  8. 数据结构与算法学习④(哈夫曼树 图 分治回溯和递归)

    数据结构与算法学习④(哈夫曼树 图 回溯和递归 数据结构与算法学习④ 1.哈夫曼树 1.1.相关概念 1.2.哈夫曼树的构建 1.3.哈夫曼编码 1.4.面试题 2.图 2.1.图的相关概念 2.2. ...

  9. 《数据结构、算法与应用 —— C++语言描述》学习笔记 — 回溯法

    <数据结构.算法与应用 -- C++语言描述>学习笔记 - 回溯法 一.算法思想 二.货箱装载 1.问题描述 2.回溯算法 3.实现 4.测试代码 一.算法思想 回溯法是搜索问题解的一种系 ...

  10. 防劝退!数据结构和算法难理解?可视化动画带你轻松透彻理解!

    大家好,我是 Rocky0429,一个连数据结构和算法都不会的蒟蒻- 学过数据结构和算法的都知道这玩意儿不好学,没学过的经常听到这样的说法还没学就觉得难,其实难吗?真难! 难在哪呢?当年我还是个小蒟蒻 ...

最新文章

  1. Delphi 中的 Var buffer 开类型参数
  2. Android Studio 3.1.4 报错Failed to find style 'coordinatorLayoutStyle' in current theme
  3. TensorFlow第六步: 继续挖坑 用tf重写BP并增加SGD
  4. 天涯明月刀怎么导入php捏脸数据,天涯明月刀捏脸数据怎么导入 天涯明月刀捏脸数据在哪...
  5. python 保留的类标识符
  6. 春运车票为谁“秒空”?第三方软件的困与危
  7. 大型网站性能优化途径
  8. 蠕虫病毒通过什么侵入计算机系统,注意!蠕虫病毒入侵!我区已有单位个人计算机中招!...
  9. linux ora-00322,ASM丢失disk header导致ORA-15032、ORA-15040、ORA-15042 Diskgroup无法mount
  10. [la P4487] Exclusive-OR
  11. 【python Windows安装教程】
  12. linux使用certbot,如何自动续期~
  13. 黑小米真不应该,如今它已是国货之光,成为国产手机在海外领军者
  14. 最新抖音X-Bogus、msToken、_signature、ttwid、webid分析(2023-04-12)
  15. [Unity-26] AnimationClip压缩-动画文件压缩
  16. sftp stp差异
  17. 获诱人的实习offer、在Kaggle推AI大赛,大二学生如何做到?
  18. 平面几何----用梅涅劳斯定理证明笛沙格定理
  19. Iconfont 开源库 Iconic 使用 方便你使用svg图片。随意更改你的色调。
  20. 哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级) 小乐乐的组合数+

热门文章

  1. 程序员合同日期不到想辞职_辞职理由怎么说才合适?实话实说,随便编一个都不行...
  2. 如何快速去掉word页眉横线
  3. c语言如何文件指针指向开头,fseek设置好文件指针 在C语言中fseek()的功能
  4. 贪心科技NLP训练营成果展示(附视频回放)
  5. linux pack文件镜像,使用buildpack-deps 构建自己的入容器镜像
  6. 如何把微信消息或者短信实时转发到另一个手机上
  7. Java 读取Doc/Docx 文档
  8. Distance from a point to a hyperplane
  9. 黑苹果10.14.5安装WebDriver驱动nvidia独立显卡
  10. java通过url获取网页内容_java通过url获取网页内容