当前位置: 首页 > news >正文

【递归,搜索与回溯算法】穷举 vs 暴搜 vs 深搜 vs 回溯 vs 剪枝算法入门专题详解

    

 


     前言     

    什么是回溯算法?    


  • 回溯算法是一种经典的递归算法,通常用于解决组合问题、排列问题和搜索问题等。

     回溯算法的基本思想     


  • 从一个初始状态开始,按照一定的规则向前搜索,当搜索到某个状态无法前进时,回退到前一个状态,再按照其他的规则搜索。
  • 回溯算法在搜索过程中维护一个状态树,通过遍历状态树来实现对所有可能解的搜索。

    回溯算法的核心思想    


  • “试错”,即在搜索过程中不断地做出选择,如果选择正确,则继续向前搜索;
  • 否则,回退到上一个状态,重新做出选择。
  • 回溯算法通常用于解决具有多个解,且每个解都需要搜索才能找到的问题。

     回溯算法的应用     


    总结    
  • 回溯算法是一种非常重要的算法,可以解决许多组合问题、排列问题和搜索问题等。回溯算法的核心思想是搜索状态树,通过遍历状态树来实现对所有可能解的搜索。
  • 回溯算法的模板非常简单,但是实现起来需要注意一些细节,比如如何做出选择、如何撤销选择等。


全排列


    1. 题目解析    



    2. 算法原理    


    解法 一 : 暴力枚举    


我们可以定义三层 for 循环,来解决这道问题;但是如果要枚举的数数量非常大呢?我们肯定不可能嵌套太多层循环; 


    解法二:递归    


像这种穷举的题目,使用暴力枚举是非常麻烦的,此时,我们可以使用递归;不同回溯的题使用模板是有出入的,我们做这类递归回溯的题,最重要弄清楚背后的原理,要能够清楚地画出决策树,很多时候模板会限制我们的思维;


    2.1 决策树     


   2.1.1 决策树的定义   


   2.1.2 画出决策树    

把每一步的决策画出来,我们就可以实现不重不漏地枚举出所有的情况,最开始的节点表示刚开始的位置枚举的所有节点; 


   2.2 全局变量    


    2.2.1 全局变量的定义方法    


需要一个全局变量的 List<List<Integer>> ,来记录我们的最终结果; 

两种方法都能起到记录的效果,但是最好还是在方法外单独定义出来这个全局变量;只需要在方法中重新实例化全局变量即可


    2.2.2 定义全局变量    




   2.3 dfs() 函数    



仅需关心某一个节点在做什么:


   2.4 处理细节问题    


    2.4.1 递归出口    


在决策树中,我们不需要遍历被剪枝的节点所在的路径,所以在遍历到决策树的叶子节点时,直接添加结果即可;如果 path.size() == nums.length,说明已经遍历该路径所有节点,类似 root==null;

那可以在返回之前,add 之后,先恢复现场吗?可以,但是没必要;我们可以回溯到上一层之后,再统一进行恢复现场;


    2.4.2 剪枝     


我们对决策树的一层剪枝进行分析,通过分析设置出剪枝对应的操作 

 


定义全局变量 check 数组

boolean 数组的作用:标记在某一条路径上,当前遍历的数对应的nums的下标的使用情况;


boolean 元素记录的是 nums 数组对应的下标,而不是下标对应的元素,如果在递归到下一个数,发现这个数对应 check 的元素是 true,则说明当前遍历元素是重复元素,也因此无法进入判断条件:


    2.4.3 回溯    


当递归到决策树的最后一层,需要把 path 回溯给上一层,此时需要恢复现场用于其他分支的递归,所以需要去掉最后一个元素;

因为 check 数组也是全局变量,所以我们需要对 path 和 check 同时进行恢复现场;



   2.5  总结    


   3. 编写代码    



 子集


     题目解析   



    算法原理    


     解法一:固定一个元素,枚举下一个元素选或不选     


  


    决策树     

   全局变量    



    设计函数结构    


 根据这个决策树,我们设计出函数头 dfs( nums , i )


  


    解法二:根据子集的元素个数,枚举所有子集    



     决策树     


 

注意:决策树执行添加元素的操作前,要先从子集末尾元素来判断是否可以添加;如 [1 , 2 ] 子集,可以添加子集个数为 [ 1 , 2 , 3 ],如果是 [ 2 , 3 ] ,[ 3 ] 这样的子集,则不能继续添加元素;

    全局变量    



    设计函数结构     



从两棵树的节点个数来看,第二棵决策树是优于第一棵决策树的;


    编写代码    


     解法一:   


     解法二:    


    

 


http://www.mrgr.cn/news/80634.html

相关文章:

  • 实习冲刺数据库练习-01 基础查询
  • 搭建私有链
  • AI自我进化的新篇章:谷歌DeepMind推出苏格拉底式学习,语言游戏解锁无限潜能
  • 网络时延由哪几部分构成,哪部分可以为0
  • 贪心算法求解跳跃游戏
  • Linux内核 -- 唤醒 `wait_event_interruptible` 等待状态的方案
  • “年轻科技旗舰”爱玛A7 Plus正式发布,全国售价4999元
  • AMS1117芯片驱动电路·降压芯片的驱动电路详解
  • linux - 软硬链接
  • Linux -- 线程控制相关的函数
  • C语言栈和队列
  • 麒麟操作系统服务架构保姆级教程(二)sersync、lsync备份和NFS持久化存储
  • 多模态抽取图片信息的 Prompt
  • 挑战一个月基本掌握C++(第五天)了解运算符,循环,判断
  • 【Rust自学】3.5. 控制流:if else
  • 【C++复习第5小节】类和对象
  • 深入解析二叉树算法
  • SpringBoot开发——整合JSONPath解析JSON信息
  • tcp_retransmit_skb函数
  • C语言指针与数组深入剖析及优化示例 指针解读 数组与指针的关系
  • vue3前端组件库的搭建与发布(一)
  • 什么是动态网站 ,有哪些特点
  • abc 384 D(子数组->前缀和) +E(bfs 扩展的时候 按照数值去扩展)
  • 程序的基本结构
  • Android 10.0 adb install执行安装过程分析二
  • Linux(一次性和周期性任务cron)