五大类常见算法 (递归与分治,动态规划,贪心,回溯,分支界限法)

五大类常见算法 (递归与分治,动态规划,贪心,回溯,分支界限法)


系统地刷 LeetCode 算法题之前,先从 宏观上了解一下这五大算法

经典例题

列举五大算法及其解决的一些经典问题:

算法经典例题
递归Fibonacci数列,阶乘,Hanoi塔
分治二分搜索、快速排序、合并排序
动态规划最长公共子序列;找零钱; 最大连续子序列和;走方格/台阶
贪心哈夫曼编码;单源最短路径(Dijkstra算法);最小生成树(Prim和Kruskal算法)
回溯0-1背包问题,八皇后,图的m着色,迷宫问题,旅行售货员
分支界限法单源最短路径 ,最大团,最小重量机器设计问题

接下来介绍每一种算法的定义与思想:

一、递归与分治

1.基本概念

  1. 递归:直接或间接地调用自身的算法
  2. 分治法的思想是:将一个规模为N、难以解决的问题,分解为k个规模较小的子问题,这些子问题相互独立且与原问题同样。 递归地解这些子问题,然后将各子问题的解合并得到原问题的解。

2.解决思想

  1. 递归
    可分为三个步骤:(以Fibonacci数为例子f(n)=n!,计算10!):
    1)明确函数功能 :计算阶乘10!
    2)明确递归结束的条件:n=10
    3)找到函数的等价关系式: f(n)= n * f(n-1)

  2. 分治法的思想
    分治法,即“分而治之”,可分为三个步骤(以二分查找为例):
    1)分解:将问题分解为若干个独立的子问题:查找左子树、查找右子树
    2)解决:若子问题规模小直接解决,若规模大则递归解决子问题:查找左子树的如果难以查找则再次分为左右子树,否则直接查找;右子树同理
    3)合并:将各个子问题的解合并:合并所有子树的查找结果

分治法最大的好处是降低了时间复杂度,入二分查找为O(logN)

二、动态规划

1.基本概念

动态规划:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,这种多阶段最优化决策解决问题的过程就称为动态规划。

动态规划经常常使用于解决最优化问题,这些问题多表现为多阶段决策。

2.解决办法

分治法类似,将待问题分解成若干个子问题(每一个问题相应一个阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了实用的信息。

在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其它局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

因为动态规划解决的问题多数有重叠子问题这个特点,为降低反复计算,对每个子问题仅仅解一次,将其不同阶段的不同状态保存在一个二维数组中。

3.问题性质
能采用动态规划求解的问题的一般要具有3个性质:

(1)最优化原理:假设问题的最优解所包括的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。

(2)无后效性:某状态以后的过程不影响曾经状态,仅与当前状态有关。

(3)有重叠子问题:子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。

4.与分治法的区别

动态规划法分解得到的子问题往往不是互相独立的

5.求解方法

求解动态规划的核心是:写出状态转移方程

动态规划的问题 = 多阶段决策问题,由初始状态开始,对中间阶段决策的选择,达到结束状态。这些决策形成了一个决策序列,同时确定了完成整个过程的一条活动路线:

         初始状态→│决策1│→│决策2│→…→│决策n│→结束状态

                       图1 动态规划决策过程示意图

(1)划分阶段:把问题分为若干个阶段,划分后的阶段是有序的或可排序的

(2)确定状态和状态变量:将问题发展到各个阶段的状态表示出来,状态的选择满足无后效性。

(3)确定决策并写出状态转移方程:状态转移是根据上一阶段的状态和决策来导出本阶段的状态。确定了决策,状态转移方程也就确定。但实际上常常反过来,根据相邻状态的关系确定状态转移方程。

(4)寻找边界条件:给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。

一般,只要解决问题的阶段、状态和状态转移决策确定了,就可以写出状态转移方程(包括边界条件)。

实际应用中可以按以下几个简化的步骤进行设计:

(1)分析最优解的性质,并刻画其结构特征。

(2)递归的定义最优解。

(3)以自底向上或自顶向下的记忆化方式(备忘录法)计算出最优值。

(4)根据计算优值时得到的信息,构造问题的最优解。

三、贪心

1.基本概念

贪心算法在策略的运行过程中,总是做出对当前看来是最好的选择。也就是说贪心算法并不从整理最优上进行考虑,它所做出的选择仅仅是在某种意义上的局部最优选择。

贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性(即某个状态以后的过程不会影响以前的状态,只与当前状态有关。)

贪心算法不能保证找到的解是最优解,但在某些情况下能够是最优解的近似解,甚至是最优解。

2.算法步骤

  1. 建立数学模型描述问题
  2. 把问题分成若干个子问题
  3. 对每个子问题求解,得到子问题的局部最优解
  4. 把子问题的解局部最优解合成原来问题的一个解

3.存在的问题

  1. 不能保证求得的最后解是最佳的
  2. 不能用来求最大值或最小值的问题
  3. 只能求满足某些约束条件的可行解的范围

4.适用问题

贪心策略适用的前提是:局部最优策略能导致产生全局最优解。
实际上,贪心算法适用的情况很少。一般对一个问题分析是否适用于贪心算法,可以先选择该问题下的几个实际数据进行分析,就可以做出判断。

5.性质

所求问题的整体最优解可以通过一系列局部最优的选择,即做选择时我们只考虑对当前问题最佳的选择而不考虑子问题的结果。这是贪心算法可行的第一个基本要素。贪心算法以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。

当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用贪心算法求解的关键特征。

四、回溯

1.基本概念

回溯的思想是:把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解。

回溯法适用于组合数较大的问题,能系统地搜索到一个问题的全部解惑任一解。

其思想类同于:1.图的深度优先搜索 2.二叉树的后序遍历
(分支界限法是:广度优先遍历)

2.算法步骤

  1. 针对所给的问题,定义问题的解空间;
  2. 确定易于搜索的解空间的结构;
  3. 以DFS搜索解空间,并在搜索过程中用剪枝函数(约束条件)避免无效搜索。

详细描述是:回溯法按深度优先策略搜索问题的解空间树。首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。

3.适用问题

当问题是要求满足某种性质(约束条件)的所有解或最优解时,往往使用回溯法。它有“通用解题法”之美誉。

回溯法的实现方法有两种:递归和递推(也称迭代)。一般来说,一个问题两种方法都可以实现,只是在算法效率和设计复杂度上有区别。
(类比于图深度遍历的递归实现和非递归(递推)实现)

4.性质

其实就是对解空间的遍历,不断更新答案,以找到最优
其核心主要有三个:1.构造解空间 2.搜索策略:即深度优先搜索策略 3.剪枝:提高效率

五、分支界限法

1.与回溯法的区别

算法目标搜索方式
回溯法找出解空间树中满足约束条件的所有解深度优先
分支界限法找出满足约束条件的一个解广度优先

2.基本思想

分支界限法以广度优先或以最小耗费(最大收益)优先的方式搜索解空间。所谓“分支”就是在扩展节点处,先生成其全部儿子节点(分支),然后在从当前的活结点表中选择下一个扩展节点,继续搜索。过程中能够用约束条件,进行剪枝。

在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。

此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。

3.算法步骤

将顶点编号为0, 1, …, n-1.
每个结点包含如下信息:
u——该节点所对应的顶点
path[n]——从源点开始的路径上的顶点编号
k——当前搜索深度下,路径上的顶点个数
d——从源点到本节点所对应顶点的路径长度
b——经本节点到目标顶点最短路径的长度下界
bound——一个可行解的取值,当做剪枝的标准

假定源顶点为s,目标顶点为t。

在这里插入图片描述

4.常见的扩展节点的常见方式:

  1. 先进先出FIFO队列
    按照队列先进先出(FIFO)原则选取下一个节点为扩展节点。
  2. 优先队列分支界限法
    按照优先队列中规定的优先级选取优先级最高的节点成为当前扩展节点。

参考:
1.https://blog.csdn.net/qq_37763204/article/details/79394397
2.https://www.jianshu.com/p/ab89df9759c8
3.https://www.jianshu.com/p/c738c8262087

  • 16
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
分治法是一种采用递归分解的处理方法,将一个规模较大的问题分解成若干规模较小的子问题,再求解子问题,最后合并子问题的解得到原问题的解,其核心思想是将一个大问题分解为几个小问题,再将小问题的解合并为大问题的解。优势是可以大大减少计算量,适用于复杂问题,时间复杂度一般是O(nlog n),空间复杂度一般是O(log n)。应用场合有求解最大子数组、快速排序、归并排序等。贪心法是每一步都采取在当前状态下最好或最优(即最有利)的选择,使最终结果达到最优解的一种算法。它的优势是求解速度快,时间复杂度和空间复杂度都较低,适用于局部最优解,但不能求解全局最优解,常用的应用场合有求解最短路径、求解最小生成树、旅行商问题等。动态规划法是一种求解最优解的算法,它的思想是将一个复杂的问题分解成若干个子问题,再从子问题出发求解原问题,并保存子问题的最优解,从而求得原问题的最优解。优势是可以求解全局最优解,时间复杂度和空间复杂度都较低,常用的应用场合有求解最长公共子序列、最优二叉搜索树、背包问题等。回溯法是一种暴力搜索的技术,它搜索空间的所有情况,并从中找出答案,优势是可以求解全局最优解,但时间复杂度较高,常用的应用场合有求解八皇后问题、求解全排列等。分支定界法是一种混合算法,它将搜索空间分解成若干子空间,再从子空间中搜索解,优势是可以求解全局最优解,时间复杂度相对较低,常用的应用场合有求解旅行商问题,求解最大团问题等。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值