列举五大算法及其解决的一些经典问题:
算法 | 经典例题 |
---|---|
递归 | Fibonacci数列,阶乘,Hanoi塔 |
分治 | 二分搜索、快速排序、合并排序 |
动态规划 | 最长公共子序列;找零钱; 最大连续子序列和;走方格/台阶 |
贪心 | 哈夫曼编码;单源最短路径(Dijkstra算法);最小生成树(Prim和Kruskal算法) |
回溯 | 0-1背包问题,八皇后,图的m着色,迷宫问题,旅行售货员 |
分支界限法 | 单源最短路径 ,最大团,最小重量机器设计问题 |
接下来介绍每一种算法的定义与思想:
1.基本概念
2.解决思想
递归
可分为三个步骤:(以Fibonacci数为例子f(n)=n!,计算10!):
1)明确函数功能 :计算阶乘10!
2)明确递归结束的条件:n=10
3)找到函数的等价关系式: f(n)= n * f(n-1)
分治法的思想
分治法,即“分而治之”,可分为三个步骤(以二分查找为例):
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.算法步骤
3.存在的问题
4.适用问题
贪心策略适用的前提是:局部最优策略能导致产生全局最优解。
实际上,贪心算法适用的情况很少。一般对一个问题分析是否适用于贪心算法,可以先选择该问题下的几个实际数据进行分析,就可以做出判断。
5.性质
所求问题的整体最优解可以通过一系列局部最优的选择,即做选择时我们只考虑对当前问题最佳的选择而不考虑子问题的结果。这是贪心算法可行的第一个基本要素。贪心算法以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用贪心算法求解的关键特征。
1.基本概念
回溯的思想是:把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解。
回溯法适用于组合数较大的问题,能系统地搜索到一个问题的全部解惑任一解。
其思想类同于:1.图的深度优先搜索 2.二叉树的后序遍历
(分支界限法是:广度优先遍历)
2.算法步骤
详细描述是:回溯法按深度优先策略搜索问题的解空间树。首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。
3.适用问题
当问题是要求满足某种性质(约束条件)的所有解或最优解时,往往使用回溯法。它有“通用解题法”之美誉。
回溯法的实现方法有两种:递归和递推(也称迭代)。一般来说,一个问题两种方法都可以实现,只是在算法效率和设计复杂度上有区别。
(类比于图深度遍历的递归实现和非递归(递推)实现)
4.性质
其实就是对解空间的遍历,不断更新答案,以找到最优
其核心主要有三个:1.构造解空间 2.搜索策略:即深度优先搜索策略 3.剪枝:提高效率
1.与回溯法的区别
算法 | 目标 | 搜索方式 |
---|---|---|
回溯法 | 找出解空间树中满足约束条件的所有解 | 深度优先 |
分支界限法 | 找出满足约束条件的一个解 | 广度优先 |
2.基本思想
分支界限法以广度优先或以最小耗费(最大收益)优先的方式搜索解空间。所谓“分支”就是在扩展节点处,先生成其全部儿子节点(分支),然后在从当前的活结点表中选择下一个扩展节点,继续搜索。过程中能够用约束条件,进行剪枝。
在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。
此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。
3.算法步骤
将顶点编号为0, 1, …, n-1.
每个结点包含如下信息:
u——该节点所对应的顶点
path[n]——从源点开始的路径上的顶点编号
k——当前搜索深度下,路径上的顶点个数
d——从源点到本节点所对应顶点的路径长度
b——经本节点到目标顶点最短路径的长度下界
bound——一个可行解的取值,当做剪枝的标准
假定源顶点为s,目标顶点为t。
4.常见的扩展节点的常见方式:
参考:
1.https://blog.csdn.net/qq_37763204/article/details/79394397
2.https://www.jianshu.com/p/ab89df9759c8
3.https://www.jianshu.com/p/c738c8262087