算法——回溯算法

关于回溯算法:

  1. 回溯算法本质上是一种“暴力”求解的穷举算法,并没有很高的效率。但是,对于“棋盘”、“排列组合”、“子集”、“切割”等问题,常规的暴力解法(比如循环嵌套)无法解决,这时回溯算法成为一种选择。
  2. 回溯算法适合解决与“树”或者“图”有关的问题,比如“棋盘”问题是关于“图”的问题、而“排列组合”问题可以转化为“树”。
  3. 提起树和图的暴力求解,我们一般联想到递归遍历,回溯法其实就是用递归实现的,具体来说它是DFS的一种应用。所谓“回溯”指的就是按条件向深处搜索,逐步达到某一路径上所有合适的目标,走到某一步时,就会到达边界或是条件不再满足的地方,此时就退回一步重新选择。

 

如何写一个回溯算法

  1. 分为“递归”函数和“调用递归”的函数。
  2. “调用递归”的函数要找到合适的开始位置,在这一位置调用“递归”。一个递归只能处理相连区域,如果多个解之间不相连,“调用递归”的函数要找到每一个不相连的开始位置。
  3. “递归”函数编写逻辑:
    1. 终止条件:当前步不满足条件(达到边界,达到标记被标记位置,非解)时,收集结果,提前返回。
    2. 标记当前位置:标记当前位置已经被访问,防止当前路径递归时再次进入该位置形成死循环,或是避免结果重复。
    3. 收集结果:将当前节点结果添加到结果合集。
    4. 进入下一步递归:规定好递归顺序,比如树的先序中序后序,图的顺逆时针。进入递归不用考虑下一步是否需要满足条件,因为进入下一步后会先判断终止条件。
    5. 清理当前位置的标记:如果目标是路径,一般要有这一步,因为路径之间可以有重合的点,且DFS本身不会产生完全重合的路径;如果目标是点,则不需要清理标记,防止结果重复。
    6. 正常返回:当前步已经处理完成,退到上一步搜索其他目标。

 

例子:剑指offer13——机器人的运动范围

题目描述:

 

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

 

示例 1:

 

输入:m = 2, n = 3, k = 1
输出:3
示例 2:

 

输入:m = 3, n = 1, k = 0
输出:1

 

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof

 

个人题解:

 

posted @ 2021-11-16 23:09  汇编不会编  阅读(292)  评论(0)    收藏  举报