五大常用算法总结

五大常用算法:贪心,动态规划,分治,回溯,分支限界

一、各算法的基本内容

贪心算法

狭义的贪心算法指的是解最优化问题的一种特殊方法,解决过程中总是做出当下最好的选择,因为具有最优子结构的特点,局部最优解可以得到全局最优解;这种贪心算法是动态规划的一种特例。能用贪心解决的问题,也可以用动态规划解决。而广义的贪心指的是一种通用的贪心策略,基于当前局面而进行贪心决策。

基本概念:

所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。不一定是全局最优解

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

所以对所采用的贪心策略一定要仔细分析其是否满足无后效性

适用问题:

贪心策略适用的前提是:局部最优策略能导致产生全局最优解。

实际上,贪心算法适用的情况很少。一般,对一个问题分析是否适用于贪心算法,可以先选择该问题下的几个实际数据进行分析,就可做出判断。

该算法存在问题:
  1. 不能保证求得的最后解是最佳的;
  2. 不能用来求最大或最小解问题;
  3. 只能求满足某些约束条件的可行解的范围。
经典例题:

背包问题
单源最短路径 - 迪杰斯特拉法(Dijkstra)
最小生成树(MST) kruskal算法 prim算法
哈弗曼编码
生产调度

动态规划算法

基本思想

若要解一个给定问题,我们需要解其不同部分(即子问题),再合并子问题的解以得出原问题的解。 通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量: 一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。 这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。

两种方式: 自顶而下的备忘录 ; 自底向上

问题特征

最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。
重叠子问题:在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解。

适用动态规划的问题必须满足最优化原理、无后效性和重叠性。

1.最优化原理(最优子结构性质) 最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。

2.无后效性 将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。

3.子问题的重叠性 动态规划将原来具有指数级时间复杂度的搜索算法改进成了具有多项式时间复杂度的算法。其中的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其它的算法。

典型问题

01背包问题
最长公共子序列(不连续) LCS  Longest Common Subsequence
最长公共子串(连续)
KMP(字符串匹配,判断字符串f在O中是否出现及出现的位置)
N皇后问题
N*N方格内走法问题

分治算法

基本概念

“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。

基本思想及策略

分治法的设计思想是:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
  分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。
  如果原问题可分割成k个子问题,1

基本思想及策略

分治法的设计思想是:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
  分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。
  如果原问题可分割成k个子问题,1

复杂性

一个分治法将规模为n的问题分成k个规模为n/m的子问题去解。设分解阀值n0=1,且adhoc解规模为1的问题耗费1个单位时间。再设将原问题分解为k个子问题以及用merge将k个子问题的解合并为原问题的解需用f(n)个单位时间。用T(n)表示该分治法解规模为|P|=n的问题所需的计算时间,则有:
  T(n)= k T(n/m)+f(n)

经典问题

二分搜索
大整数乘法
Strassen矩阵乘法
棋盘覆盖
合并排序
快速排序
线性时间选择
最接近点对问题
循环赛日程表
汉诺塔

回溯法

思路

回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。
按照深度优先搜索的策略,从根结点出发深度探索解空间树

步骤

1 定义一个解空间,包含问题的解
2 利用适用搜索的方法组织解空间
3 深度优先搜索
4 有限界函数避免移动到不可能产生解的空间

经典例题

八皇后问题
图的着色
装置
背包
最大团

分支限界法

思想

以广度优先活最小耗费优先方式搜索解空间
每个活结点只有一次机会成为扩展结点,活结点成为扩展结点后一次性产生所有子结点,其中导致不可行解或者非优解的子结点被舍弃,其余的加入活结点
从活结点中取出一个成为扩展结点,重复第二步,直到活结点为空

两种方法

队列式(FIFO)分支限界法:按照先进先出的方式选出下一结点为扩展结点
优先队列式分支限界法:按照优先队列中优先等级选出结点为扩展结点

经典问题

单元最短路径
0-1背包
tsp问题

二、各算法之间的区别与联系

贪心算法和动态规划

共同点:
两者都有最优子结构性质
不同点:

贪心算法:
1 每一步的最优解是由上一步的最优解推导出来的,上一步之前的最优解是不保存的
2 贪心算法正确的条件:每一步的最优解一定包含上一步的解,局部最优解可以导致全局最优解
3 得到的结果不一定是全局最优解
4 一般自上而下

动态规划:
1 全局最优解一定包含某个局部最优解,但不一定是上一个最优解,因此要记录所有之前的最优解
2 每一步所做的选择依赖相关子问题,只有解出子问题才能做出选择
3 通常选择自下而上

分治和动态规划

共同点:
都是将大问题分解成若干个子问题,然后将子问题的解进行合并,形成原问题的解

区别:
分治的子问题是相互独立的,通常用递归做
动态规划的子问题相互之间有联系,有重叠部分,通常用迭代做

分支限界法和回溯法

相同:
都是在问题的解空间树上搜索问题解的算法

不同:
目的不同:回溯法一般是找出满足约束条件的所有解,分支限界法一般是找出满足条件的极大或极小解
搜索方式:回溯法以深度优先方式搜索,分支限界法是广度优先或者最小耗费优先
存储结构:回溯法堆栈,分支限界法 队列或优先队列

你可能感兴趣的:(算法)