漫话算法:一文带你搞懂递归回溯剪枝恢复现场暴搜

1.应用场景

        1.在力扣中,我们一般都按标签做题,但是如果没有标签我们如何判断使用什么算法呢,以下是我的看法

        2.递归:先观察问题的构成,如果符合两种情况,一种是大问题下包含这子问题,而大问题和子问题的解决方法十分相似,二叉树的遍历等算法就是这种类型的递归,另一种是每个子问题都一模一样,深搜相关的算法就是这种类型的递归,dp函数不断向下判断

        3.回溯:这个就是在确定递归的基础上进行的操作,是否需要回溯,取决于是否会“多分枝”,及当一个母节点同时具有多个子问题的时候,当一对母子执行完后,需要执行另一对母子,就要将操作步骤从子函数重新返回到母函数

        4.剪枝:这个不需要确定递归,而是一种普适的算法,它的目的是及时排除错误情况提升代码效率,有两种方式,一种是某情况进入函数操作,另一种是某情况不进入函数操作

        5.恢复现场:配合回溯使用,回溯时要保证子问题对其他元素造成的影响完全恢复,总体思路为动了什么就回退什么

        6.暴搜:每个情况都要试一遍,适用于无明显规律的问题

2.这类算法的小弟们

        1.全局变量:首先,全局变量的使用有两种情况,一种是作为返回值,由于递归函数不是void类型会造成函数出口难以操作,所以可以将返回值作为全局变量,便于操作,另一种是函数中要频繁使用的变量,会使代码变得简洁,还有一种是在多个函数中出现的变量,我们一般定义为全局变量

        2.递归出口:可能年少的你对于递归出口有很多疑问,但是请记住,return的出现意味着函数的结束,虽然这个函数可能只是上一级递归函数中的语句,但是请注意这个函数的形参值已经完全被释放,所以,将某个值作为递归的形参可以起到恢复现场的作用

        3.check数组:它由bool值组成,是否使用它主要取决于能不能走回头路,如果走回头路是不被允许的,则必须引入check数组

        4.结果的改变:关于结果的讨论一般存在于子集问题中,改变返回值在递归出口还是每个函数的开头取决于结果是否必须等于某个长度

        5.dps函数,一般使用void类型,但是有时候需要一层一层的递归提供的信息来剪枝,则选择bool或者其他类型

        6.递归的入口:树的入口是根节点不必多少,但在一些复杂的矩阵问题中,可能入口是某个位置,需要具体情况具体分析。

        7.dps函数的递归标志:一般为执行次数,层数,长度等多种变量,用于递归的推进

        8.多递归:当存在多个递归关系时,需要判断这些递归之间的关系,一种就像二叉树的左右子树一样,同时存在,则选取某种顺序进行遍历,而这些递归会同时存在,另一种则是“你死我活”的关系,需要配合剪枝判断

        9.哈希表:check数组就是一个简单的哈希表,而哈希表在映射数据以判断是否需要剪枝中有更广泛的运用

        10.向量法:在矩阵中走迷宫时,四个方向可以定义两个映射数组dx{1,-1,0,0},dy{0,0,-1,1},在走迷宫时直接循环遍历四个情况的向量

3.套路

        1.定义全局变量

        2.主函数:首先对数据进行优化(需不需要排序什么的),然后寻找递归入口,判断是否存在多递归,然后对递归进行调用

        3.递归函数:首先写递归出口(包括返回结果),然后进行内层递归调用