常用算法模板(递归、分治、贪心、动态规划、回溯)

一、递归算法

递归算法:是指一种通过重复将问题分节为同类的子问题而解决问题的方法。它能解决的问题有①数据的定义是按递归定义的,如斐波拉契数;②问题解法按递归算法实现,如汉诺塔问题;③数据的结构形式是按递归定义的,如二叉树和广义表等。

递归算法的模板如下:

void 递归函数(参数)

{

       if(结束条件)  //达到了结束的条件,即可执行当前的函数体并返回结果

      {

              //做输出结果的功能,并结束运行

      }

      else   //未达到结束条件

     {

             //执行当前的操作

            //改变条件和参数,进行下次的操作

      }

}


它的调用过程为:①计算参数值,将函数压栈;②执行递归函数;③满足结束条件,结束函数,返回上层函数;

递归算法最常用的一些地方举例:①全排列;②斐波拉契数;③阶乘;④汉诺塔;⑤排列组合;⑥归并排序。


注意:递归一般需要有边界条件、递归前进段、递归返回段,当不满足边界条件时,递归前进,满足时进行返回操作。

二、分治算法

分治算法:是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原文太性质相同,所以求出子问题的解,就能得到原文太的解,是一种分目标完成的算法,简单的问题用二分法即可解决。

分治算法的模板如下:

type  DaC(Partition)

{

        if |Partition|≤n0
                then return(this->Partition)
       else

             将Partition分解为较小的子问题 P1 ,P2 ,...,Pk
       for i←1 to k
            do yi ← DaC(Pi)    // 递归解决Pi
       T ← MERGE(y1,y2,...,yk)   // 合并子问题
       return(T)

}


它的解题步骤为:①分解:将要解决的问题分成若干同类子问题;②求解:当子问题够小时,用较简单的方法解决;③合并:按原问题的要求,将子问题的解逐层合并构成原问题的解;

分治算法常用场景:①求最值;②二分搜索;③快速排序;④堆排序;


注意:分治算法需要保证原问题可以分解,然后由终止条件,最后则是可以合并为原问题

三、贪心算法

贪心算法:指在对问题求解时,总是做出在当前来看是最好的选择,也就是说,不从整体最优上来考虑答案,而是从局部上获得某种意义上的最优解。

贪心算法的模板是:

从问题某一初始解出发;

while(能朝给定总目标前进一步)

{

       利用可行的策略,求出一个局部最优解;

}

由所有局部最优解合成问题的一个可行解;


它的解题步骤为:①把求解问题分成若干子问题;②对每一个子问题求解,得到子问题的局部最优解;③把子问题对应的局部最优解合成原来的整个问题的一个近似最优解;

贪心算法常用场景:割绳子、钱币找零问题、最优装载问题、迪杰斯特拉算法、求最小生成树的Prim算法和Kruskal算法


注意:贪心算法不能保证一定求得的是最优解,一般是用来解决求最大或最小问题的,也只能确定某些问题的可行性范围

四、动态规划

动态规划:是运筹学的一个分支,是求解决策过程最优化的过程,主要用于求解以时间划分阶段的动态过程的优化问题,但是一些与时间无关的静态规划(如线性规划、非线性规划),只要人为地引进时间因素,把它视为多阶段决策过程,也可以用动态规划方法方便地求解。

动态规划的模板是:

def dynamicPro(nums):
    if not nums or not nums[0]:
        return 
    m,n = len(nums), len(nums[0])
    dp = [[0 for _ in range(m)] for _ in range(n)]
    dp[0][0], dp[0][1] = x,y  
    for i in range(m):
        for j in range(n):
            dp[i][j] = max/min(
                dp[i-1][j-1],dp[i-1][j],dp[i][j-1])
    return dp[m-1][n-1]


它的解题步骤:①判断是否符合最优子结构性质。符合进入步骤2,否则不能用动态规划计算;②建立子问题的递归关系式;③依据递归关系式按顺序解决需要解决的子问题,并将结果存储(一般使用***数组);④依据存储的结果获取求解答案;

动态规划常用场景:最优子结构、重叠子问题、背包问题、最长公共子序列、最优二分检索树


注意:动态规划的问题必须满足最优化原理和无后效性;即最优化原理:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略;无后效性:每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性

五、回溯算法

回溯算法:实际上是一个类似于枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

回溯算法的模板是:

begin 

              for i:=1 to 边界 Do  {枚举所有方法}

                        begin 

                              保存结果 

                              if  达到目的  then  输出解结果

                              else Try(k+1); 

                              恢复:保存结果之前的状态{回溯一步} 

                         end; 

end; 


它的解题步骤为:①针对问题,定义问题的解空间,它至少包含一个最优解;②确定易于搜索的解空间结构,使得能用回溯法方便的搜索整个空间;③以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索;

回溯算法常用场景为:八皇后问题、0-1背包问题、迷宫问题、寻找最优子集;


注意:需要考虑路径、选择列表和结束条件,路径:也就是已经做出的选择;选择列表:也就是你当前可以做的选择;结束条件:也就是到达决策树底层,无法再做选择的条件。

你可能感兴趣的:(知识积累和分享,c++,算法,linux,经验分享)