算法分析与设计复习算法
算法分析与设计复习
2016年初,研一上学期期末考试前,复习并总结算法分析与设计科目的内容。复习过程参照《算法导论》中文第2版,同时参照PPT,章节划分根据PPT内容数组
概要:函数
第一章 概述优化
第二章 插入排序&分治策略编码
第三章 复杂度分析设计
第四章 堆与堆排序3d
第五章 快速排序blog
第六章 线性时间排序排序
第七章 中位数和顺序统计递归
第八章 动态规划(DP)
第九章 贪心算法
第十章 最短路径算法
第十一章 回溯法&分支限界法
第十二章 NP问题与一些概念
第一章 概述
-
算法的应用范围
算法在诸如生物等诸多领域有其应用
-
算法的意义
算法在不少状况下让不可能完成的事情变成了可能,让处理的很慢的过程变快。
-
一个铺垫
一串不全为负的数,怎么取能拿到一段和最大的子串(最大子段和)
第二章 插入排序&分治策略
-
插入排序
- 掌握插入排序的方法
-
循环不变式的证实
初始化:
保持:
终止:
-
逐步计算插入排序的时间复杂度:
结论(基于RAM模型下):
Best Case:O(n)
Worst Case:O(n^2)
-
分治策略
-
MERGE Sort
- 掌握归并排序的方法
-
分析归并排序
- 经过递归式分析
- Best case:nlgn
- Worst case:nlgn
-
课后习题总结
- 推演一个插入排序的过程
- 循环不变式证实线性查找的正确性
- 对给定的时间复杂度表达式写出Θ
- 推演一个MERGE Sort
- 算法设计题:能够看*
第三章 复杂度分析
-
时间复杂度分析
-
归并排序分析
-
代换法(证实手段)
- 作一个好的猜想
- 假设这个界对某一个范围内成立
- 带入得出结论
- 数学概括法证实结论正确
-
递归树
- 时间复杂度的表达式是每一层拆分开销之和加上最底层每个未知的开销。
-
主定理(必会)
- 形如:T(n)=aT(n/b)+f(n)
-
三种状况:
- 若存在ε>0,有f(n)=O(n^(log b(a)-ε)),则T(n)=Θ(n^(log b(a)))
- 若f(n)=Θ(n^(log b(a))),T(n)=Θ(n^(log b(a))lg(n))
- 若对某ε>0,有f(n)=Ω(n^(log b(a)+ ε)),且对常数c<1与全部足够大的n,有af(n/b)<=cf(n),则T(n)=Θ(f(n))
-
必会技能
-
课后习题总结
-
代换法证实时间复杂度
- 猜想渐进确界,证实之
- 主方法可用状况的练习
- 判断主方法是否可用,肯定渐进上界
第四章 堆与堆排序
-
堆的概念
- 利用树的数组存储方式,PARENT(i) = i/2, LEFT(i) = 2i, RIGHT(i) = 2i + 1
-
两个关键的函数
- MAX-HEAPIFY 已有堆的状况下,加入新结点后调整堆以使得其知足堆的条件。O(lgn)
- BUILD-MAX-HEAP 基于无序数组调整为大顶堆Θ(n)
- 其中,BUILD-MAX-HEAP是由(n/2)向下取整次MAX-HEAPIFY组成的,但其时间复杂度是Θ(n)
-
堆排序时间复杂度
- 时间复杂度由两部分组成,1次BUILD-MAX-HEAP,n-1次MAX-HEAPIFY,故结果为T(n)=Θ(n)+nO(lg n)=O(nlgn)
- 最好的状况下,时间复杂度为O(n)
- 优先级队列
-
必会技能:
-
课后习题总结:
- 区分一个序列是否为最大堆
- 画出一个完整的MAX-HEAPIFY流程
第五章 快速排序
-
快速排序
-
时间复杂度
- 最好Θ(nlgn)
- 平均Θ(nlgn)
- 最坏Θ(n2)
- 知道分治的过程————以一个数作分治,分红两组
- 掌握快排的手动作法
- 有一个关于每次都从1/10位置分隔的状况下仍为nlgn的证实
-
随机快排
- 关键:用随机来避免出现Worst case
- 实际表现是最快的排序
-
时间复杂度
- 平均Θ(nlgn)
- 最坏Θ(n2) (仅在理论上存在)
-
课后习题总结
- 若快排数组中元素都同样,时间复杂度是多少?
- 答:这是Worst Case 因此是Θ(n2)
第六章 线性时间排序
- BDD证实基于比较排序最坏状况的最小量级是nlgn
-
计数排序
- 计数排序是一种稳定排序
- 时间复杂度Θ(k+n) ,在k与n同一数量级时,该复杂度为O(n)
-
关键:被排序的n个数在0~k之间
- 范围不能超过数的个数的量级
- 若这n个数的范围是n^2,则时间复杂度再也不是O(n),而是O(n^2)
-
掌握计数排序的完整过程,能够手跑
- 建立一个容量为k的数组C,并将全部元素置零
- 遍历原数组A,在C中对应的位置+1
- 遍历数组C,从第2个元素开始的全部元素的值依次用前一个元素与当前元素的和替换。
- 逆序遍历A,拿到元素a,在C中查找其位置(即C中元素对应的数值)在数组B中的对应位置放入a便可。同时将C中的那个数据-1
-
基数排序
- 掌握基数排序的完整过程,能够手跑
- 基数排序的特色:利用稳定排序的特色,从低位到高位按位排序
-
时间复杂度
- Θ(d T(n))
- 在每位计算使用计数排序的时候,时间复杂度为Θ(n)
-
桶排序
- 掌握桶排序的完整过程,能够手跑
- 主要针对均匀分布的数,利用哈西,靠散列的过程完成排序
- 要点:相似于计数排序,为待排序数组提供若干个区间,将各个待排序的数放进区间内,完成区间内排序的同时,就获得了一个完整的排序结果。
-
算法小结

-
课后习题总结
第七章 中位数和顺序统计
- 找到最大值/最小值的方法:找到最值Θ(n),从头至尾遍历,每一步记下当前的最值,结果就是最后的结果
-
查找第i个元素的随机算法
- 存在Worst Case能够在线性时间完成计算的算法
-
了解PARTITION函数的做用及原理
- 该函数利用随机数,拿到一个区间内的某数a,运行一次partition后,能保证以a为界将原区间分为两个部分,选这两个部分中的一部分继续partition
- 优化后的partition主要在随机拿到划分元素上下功夫,经过将全部元素5个一组分红小组,组内找出中位数,用全部的中位数再找出中位数a后,以a为界划分两个部分,不断循环,这样能保证划分的质量。
第八章 动态规划(DP)
-
动态规划问题的四个基本步骤
- 肯定最优解的结构。(DP的必要条件)
- 递归定义最优解的值。
- 自底向上计算解的值。
- 利用计算获得的信息构造最优解。
-
装配线调度问题
- 关键:问题的最优解包含其子问题的最优解
-
递推关系式

-
矩阵链乘
- 关键:拆分后的矩阵链也要以最少的计算次数才能获得正确的结果
-
递推关系式

-
示意图

-
DP问题的要素:最优子结构
- 有向图中两节点的最短路径长度是有最优子结构的
- 有向图中两节点的最长路径长度没有最优子结构
- 最短路径长度与最长路径长度的区别是是子问题是否独立。
-
自上而下与自底向上之间的比较
-
自上而下的递归形式算法
-
自底向上的动态规划算法
- 没有重复计算,但可能存在多余计算,即计算并不会用到的数据
-
备忘录以及应用备忘录后两种形式算法的对比
- 备忘录经过记录计算过的子问题,避免了在自上而下进行递归计算时,重复计算的问题
-
自底向上的动态规划方法
-
自上而下+备忘录
-
最长公共子序列(Longest common subsequence/LCS)
- 暴力算法:查找全部子串,时间复杂度是指数级
-
DP求解LCS原理
- 两字符串A(m)、B(n),若最后一个字符相同则必定在其某个最长公共子序列C内,故C的长度为1+LCS(A(m-1),B(n-1))
- 两字符串A(m)、B(n),若最后一个字符不相同,则C的长度为max{LCS(A(m-1),B(n)),LCS(A(m),B(n-1))}
- 因为上两条,故LCS由AB某一子字符短的LCS组成,故具备最优子结构
-
DP求解LCS图解

-
图解的解释:
-
最大子段和
-
DP求解最大子段和的原理
- 最大子段和必定是某个元素a加上了前面的某一个子段和或者是a元素自己。
-
DP求解数组A最大子段和过程
- B[0]=A[0]
- B[1…n]=max{B[1…n], B[0…n-1]+ B[1…n]}
- 遍历B,其中的最值就是最大子段和
-
课后习题总结
- 修改原算法使其能顺序输出装配结果
- 推演一个矩阵链乘的最优加括号方式
- 推演两个字符序列的LCS
第九章 贪心算法
-
贪心策略
- 贪心选择性质:贪心策略但愿经过局部选择最优达到全局最优的目的。可是并非全部状况都能达到全局最优。
-
活动选择问题
-
背包问题
包含0-1背包、分数背包两个子问题
- 讨论目的:从两种背包问题中对比动态规划与贪心算法
-
异同点
- 共同点:均有最优子结构,符合动态规划问题的求解条件
-
不一样点:针对同一物品肯定是否选择状况
- 分数背包:性价比最高的,必定在最优子结构中,由于其余的物品都达不到这种评价标准
- 0-1背包:不肯定,须要对全部状况予以讨论
-
解决策略:
-
分数背包:贪心算法
- 具体方法:把当前性价比最高的物品装到不能再装(没有了或者包满了)为止
-
0-1背包:DP
-
具体作法:刻画最优子结构,标准DP作法

-
哈夫曼编码
利用变长编码使编码长度大大减少,原理:频率越高的字符,表示的编码越短。
第十章 最短路径算法
最短路径算法包含单源最短路径、每对结点间的最短路径。。。。
-
关于最短路径概念的讨论
- 最短路径知足最优子结构,即:一个最短路径a中的任意两点的最短路径b必定在a的路径中
- 三角不等式:对于全部的 u,v,x∈V, 如下不等式成立 δ(u,v) ≤δ(u,x)+δ(x,v)
- 含有负环的图中,某些最短路径可能不存在
- 单源最短路径:求解从一个点到其余全部点的最短路径的集合
-
狄杰斯特拉算法(单源)
狄杰斯特拉算法本质上利用了贪心思想,不断的更新当前最短路径,用来处理不含负边的图
- 时间复杂度:O(E+VlgV)
-
算法流程:
- 把原点a加入图中。
- 记录全部从原点能到达的结点的路径长度,其余的记为∞
-
重复如下几步,直到全部节点都记录在图中
- 选出未记录到图中的路径v最小的那个结点p
- 把结点p加入图中
- 用vp+p到其余结点的路径长度与原记录中的最短路径对比,记下小的那个
-
无权图的最短路径算法(单源)
无权图由狄杰斯特拉算法退化而来,经过广度优先的的搜索模式记录最短路径
-
Bellman-Ford算法 (单源)
Bellman-Ford算法能够处理含有负边、负环的图,若是存在负环,则能报告由环为负环
- 时间复杂度:O(VE)
-
算法流程:
- 初始化全部结点,到各结点的最短路径初始化为∞
-
执行如下流程n-1次(n为结点个数)
- 遍历每个边,若是经过这个边能使目的结点的最短路径更小,就更新它
- 再执行一次循环中的过程,如有更改的结点则说明存在负环。不然返回当前结果
- 特色:好写,时间复杂度高
-
每对结点间最短路径
- V次Dijkstra:O(VE+V^2lgV)
-
V次Bellman-Ford:O(V^2E)
-
每对结点间最短路径第一种算法(矩阵“乘”)
- 原理:同时对全部节点同时进行一次Bellman-Ford操做
-
步骤:
- 证实:略
-
改进的矩阵“乘法”
- 每次都是对A进行这种乘法,能够每次都计算A^2这种算法
- 原理:因为利用三角不等式,因此三角不等式中的两小段路径不必定是1和k-1的关系。也多是m和n之间的关系。能够作这种偷懒简化。
-
每对结点间最短路径第二种算法(Floyd)
- 归纳:从1个点开始不断往图中增长点,若是新加入的点可以对当前的最短路径产生影响的话,就更新当前的最短路径结果表;约束过哪些结点
-
递归式:

-
流程:
- 初始化一个矩阵存储方式的V个边的图
-
循环下列步骤V次,记当前次数为k
- 对每一条路径判断,被k分为两段的该路径是否会获得更小的结果,用较小值更新它
-
每对结点间最短路径第三种算法(Johnson)
- 归纳:为了利用Dijkstra算法,因而经过更改权值,消除负权值以知足Dijkstra。由于Dijkstra代价小
-
课后习题总结
- 推演一个Bellman-Ford算法
- 推演一个矩阵“乘”算法
- 推演一个Floyd算法
第十一章 回溯法&分支限界法
回溯法和分支限界法都是搜索搜索方式,当DP、贪心这些方法没有办法使用时,只能经过搜索来找到结果。搜索的方法主要包括这两类。回溯法是一种深度优先的搜索方式
-
n皇后问题(回溯法)
- 解空间具备n!个n元组组成
-
算法步骤:
- 注意限界函数:不与其它皇后冲突
-
15迷问题(分支限界法)
-
子集合数(回溯法)
- 限界函数:既不超过目标数,剩下的数字和还大于距目标数的差距
-
01背包(回溯法)
- 限界函数:还有可能(经过分数背包计算剩下的产品价值)产生比当前的最优解好的状况才继续搜索
-
回溯法的通常方法
第十二章 NP问题与一些概念
-
可计算性
- 不是全部问题都是可计算的
- 普斯特竞赛问题(不可求解)
- 有限步操做肯定一个给定的多元多项式是否有整数根问题(不可求解)
-
停机问题(不可求解)
-
NP彻底
- P:在肯定化的图灵机上可在多项式级计算时间内求解的可断定问题集合。
- EXP:在肯定化的图灵机上可在指数级计算时间内求解的可断定问题集合。
- NP:存在有效验证算法的可断定问题集合
-
NPC:NP集合中具备以下性质的问题:若该问题可被有效求解,则其求解方法可被用于有效求解其它NP彻底问题。
- TSP:找到可否在距离D内访问N个城市
- 三色问题:用三个颜色为地图上色,要求邻国颜色不同
- SAT:电路可知足性
-
如何面对NPC问题?若是一个问题是NP彻底问题,则咱们所设计的算法最多能同时作到如下三点中的两点:
- 求解问题的最优解
- 在多项式级时间内求解
- 求解问题的任一实例