算法设计知识点整理
基础知识
渐进符号
渐进紧确界
三种符号图例如下:
分析方法
三种分析标准:最好情况分析、最差情况分析、平均(期望)情况分析。
和式求解
主定理法
对形如
进一步推导得出:当
特别的,如果
分治算法
算法原理
分解为子问题,递归求解,合并子问题。
经典问题
归并排序
对于一串数字数组进行排序。将原数组不断划分为小数组,直至该数组元素为
对数列
从小到大排序。 分组为
。 第一次归并后
,第二次归并后 ,第三次归并后 。
最大子数组
在给定的数字数组(包含正数和负数)中,找到一个连续的子数组,使得这个子数组的元素和最大。将原数组不断划分为小数组,直至该数组元素为
对数列
求最大子数组和。 分组为
。
合并,左最大值为 ,右最大值为 ,跨中点最大值为 ; 合并,左最大值为 ,右最大值为 ,跨中点最大值 ; 合并,左最大值为 ,右最大值为 ,跨中点最大值为 ; 合并,左最大值为 ,右最大值为 ,跨中点最大值为 。因此最后最大值为 ,子数组为 。
逆序计数
在给定的数字数组中,计算逆序对(
计算
中逆序对数量。 分组为
。 第一次归并后
,数量为 ;第二次归并后 ,数量为 ;第三次归并后 ,数量为 。
快速排序
对于一串数字数组进行排序。选定基准数(多为最右元素),将现数组分区,小于大于基准的分开放在左右侧,并将基准元素放在分界线处。递归继续对左右侧的数组排序,直至递归到单元素数组。时间复杂度为
对数列
从小到大排序。 以
为基准,遍历到 时,调换 与 的位置;遍历到 时,调换 与 的位置;完成遍历后,调换 和 的位置,并对 和 递归排序。 排序代码如下:
1
2
3
4
5
6
7
8
9
10
11 def qsort(arr, low, high):
if low < high:
pivot = arr[high]
i = low
for j in range(low, high):
if arr[j] <= pivot:
arr[i], arr[j] = arr[j], arr[i]
i = i + 1 # 保证arr[i]始终是从左数第一个大于基准的元素(初始i==j,直至arr[j]>pivot)
arr[i], arr[high] = arr[high], arr[i]
qsort(arr, low, i - 1)
qsort(arr, i + 1, high)
次序选择
在一个未排序的序列中找到第
动态规划
算法原理
确定转移方程,边界条件。使用时需要保证子问题的完整性,不能更改子问题部分的解。
经典问题
0-1背包
给定一组物品,每种物品都有重量和价值,物品不可以切割,放入限定重量的背包中,要求总价值最大。设立动态规划数组
有一组物品
: , 放入一个容量为 的背包中,使得总价值最大。
dp[i][j] 0 1 2 3 4 5 6 0 0 0 0 0 0 0 0 1 0 0 0 20 20 20 20 2 0 0 0 20 30 30 30 3 0 0 15 20 30 35 45 4 0 0 15 20 30 35 45 最终放入背包的是
。
最大子数组
在给定的数字数组(包含正数和负数)中,找到一个连续的子数组,使得这个子数组的元素和最大。设立动态规划数组
对数列
求最大子数组和。
dp[i] 0 1 2 3 4 5 6 7 8 9 0 -2 1 -2 4 3 5 6 1 5 最终子数组为
。
最长公共子序列
在两个数组中,找出最长的、保持相对次序的(可不连续)公共元素序列。设立动态规划数组
给定序列”ABCDGHA”和”AEDFHR”,求最长公共子序列。
dp[i][j] 0 1A 2B 3C 4D 5G 6H 7A 0 0 0 0 0 0 0 0 0 1A 0 1 1 1 1 1 1 1 2E 0 1 1 1 1 1 1 1 3D 0 1 1 1 2 2 2 2 4F 0 1 1 1 2 2 2 2 5H 0 1 1 1 2 2 3 3 6R 0 1 1 1 2 2 3 3 最终最长公共子序列为 “ADH” 。
最长公共子串
在两个数组中,找出最长的、连续的公共元素序列。设立动态规划数组
给定序列”abcdefg”和”zabcdxyz”,求最长公共子串。
dp[i][j] 0 1z 2a 3b 4c 5d 6x 7y 8z 0 0 0 0 0 0 0 0 0 0 1a 0 0 1 0 0 0 0 0 0 2b 0 0 0 2 0 0 0 0 0 3c 0 0 0 0 3 0 0 0 0 4d 0 0 0 0 0 4 0 0 0 5e 0 0 0 0 0 0 0 0 0 6f 0 0 0 0 0 0 0 0 0 7g 0 0 0 0 0 0 0 0 0 最终最长公共子串为 “abcd” 。
最小编辑距离
使用最少的插入、替换、删除操作,将一个字符串转换到另一个字符串。设立动态规划数组
给定序列”kitten”和”sitting”,求最小编辑次数。
dp[i][j] 0 1k 2i 3t 4t 5e 6n 0 0 1 2 3 4 5 6 1s 1 1 2 3 4 5 6 2i 2 2 1 2 3 4 5 3t 3 3 2 1 2 3 4 4t 4 4 3 2 1 2 3 5i 5 5 4 3 2 2 3 6n 6 6 5 4 3 3 2 7g 7 7 6 5 4 4 3 最终最小编辑次数为
,编辑操作为 , , 。
贪心算法
算法原理
构造贪心选择,方案正确性证明(重点)。
证明方法一般有:
微扰法(邻项交换):证明在任意状态下,任何对局部最优策略的微小改变都会造成整体结果变差。有时也会用相邻项交换,证明可以参考冒泡排序正确性证明。
范围缩放:证明任何对局部最优策略作用范围的扩展都不会造成整体结果变差。
决策包容性:证明在任意状态下,做出局部最优策略之后,在问题状态空间中的可达集合包含了作出其它任何决策后的可达集合。即:这个局部最优策略提供的可能性包含其它所有策略提供的可能性。
反证法。
数学归纳法。
经典问题
部分背包
给定一组物品,每种物品都有重量和价值,物品可以切割,放入限定重量的背包中,要求总价值最大。计算比价值(
证明可以使用微扰法:设划定
霍夫曼编码
霍夫曼编码是将原字符变为01数字串的编码,给定一系列符号以及使用频率,给每个符号分配编码,使得最终翻译后的数字串没有二义性且最短。按照频率构建最小堆(子节点一定大于等于父节点),接着合并节点,直至构建出霍夫曼树,按照节点位置即可获得每个符号的霍夫曼编码。时间复杂度为
证明可以使用反证法:如果霍夫曼获得的编码组
一系列符号及使用频率如下
,建立霍夫曼树。 最小堆如下:
1
2
3
4
5 B
/ \
A D
\
C初始排序为
;第一次合并 ,合并后 ;第二次合并 ,合并后 ;第三次合并 ,合并后 。合并后霍夫曼树如下:
1
2
3
4
5 33
/ \
12 21
/ \ / \
B D A C最终编码为
, , , 。
活动选择
给定一系列具有开始和结束时刻的活动,选择尽可能多的活动,并使得这些活动参与时间无重叠。按照结束时间从小到达排序,选择结束时刻更早的一系列活动。时间复杂度为
证明可以使用反证法:如果该算法获得的选择
图算法
图的基本概念
图由点(Vertice)和边(Edge)构成,可表示为
度是指和点相连的边的数量,等于入度与出度之和。
路径是指从起点到终点一系列相连边所组成的集合(如果一条路径每个顶点只经过一次,即无环路,则称其为简单路径)。
如果两个点之间有一条路径,那么称为两点是连通的,可达的。
图搜索算法
有多种搜索问题,搜索从一个顶点到另一个顶点的全部路径,从一个顶点出发遍历全图等等。
广度优先搜索
设置一个队列存储待搜索点的顺序。每次出队一个节点元素,从这个节点出发,将周边节点全部加入队列中,继续搜索,直至完成目标。搜索全图的时间复杂度为
深度优先搜索
从一个节点出发,搜索其周边节点,将其中一个周边节点加入路径,并从该节点出发继续搜索,直至完成目标。搜索全图的时间复杂度为
环路检测
检测图中是否存在环路或存在环路的个数。可以使用广度优先遍历或深度优先遍历完成。
拓扑排序
在有向无环图中,按照排序规则(若存在路径
对于下图进行拓扑排序。
Q T 0 614 0 143 06 432 061 32 0614 2 06143 75 061432 58 0614327 8 06143275 9 061432758 0614327589 最终顺序为
。
强连通分量
强连通指两个节点
求下图全部强连通分量。
原图的反向图为:
从节点
出发深度优先遍历确定 : 。 反向输出得到
: 。 按照
顺序对每个未访问节点开始遍历:
node visited L 10 10,11,12 1,4,6,7,8,9,5,2,3 1 1,2,3,4,6,7 8,9,5 8 8,9 5 5 5 因此最终该图的强连通分量有
。
最小生成树
在一个连通加权无向图
Prim
维护一个数组
求下图的最小生成树。
边队列 1 2,3,4,5,6,7 (1,2),(1,3) 1,2 3,4,5,6,7 (1,2) (1,3),(2,3),(2,4),(2,5) 1,2,3 4,5,6,7 (1,2),(1,3) (2,4),(2,5),(3,4),(3,6) 1,2,3,6 4,5,7 (1,2),(1,3),(3,6) (2,4),(2,5),(3,4),(6,4),(6,5),(6,7) 1,2,3,4,6 5,7 (1,2),(1,3),(3,6),(3,4) (2,5),(6,5),(6,7),(4,5) 1,2,3,4,6,7 5 (1,2),(1,3),(3,6),(3,4),(6,7) (2,5),(6,5),(4,5),(7,5) 1,2,3,4,5,6,7 (1,2),(1,3),(3,6),(3,4),(6,7),(6,5) 最终生成树中边集合为
。
Kruskal
维护一个数组
求下图的最小生成树。
边 边队列 (3,6) 1 (3,6),(3,4),(4,6),(6,7),(1,2),(5,6),(5,7),(4,5),(1,3),(2,4),(2,3),(2,5) 3,6 (3,6) (3,4) 2 (3,4),(4,6),(6,7),(1,2),(5,6),(5,7),(4,5),(1,3),(2,4),(2,3),(2,5) 3,4,6 (3,6),(3,4) (4,6) 2 (4,6),(6,7),(1,2),(5,6),(5,7),(4,5),(1,3),(2,4),(2,3),(2,5) 3,4,6 (3,6),(3,4) (6,7) 2 (6,7),(1,2),(5,6),(5,7),(4,5),(1,3),(2,4),(2,3),(2,5) 3,4,6,7 (3,6),(3,4),(6,7) (1,2) 4 (1,2),(5,6),(5,7),(4,5),(1,3),(2,4),(2,3),(2,5) 1,2,3,4,6,7 (3,6),(3,4),(6,7),(1,2) (5,6) 5 (5,6),(5,7),(4,5),(1,3),(2,4),(2,3),(2,5) 1,2,3,4,5,6,7 (3,6),(3,4),(6,7),(1,2),(5,6) (5,7) 6 (5,7),(4,5),(1,3),(2,4),(2,3),(2,5) 1,2,3,4,5,6,7 (3,6),(3,4),(6,7),(1,2),(5,6) (4,5) 7 (4,5),(1,3),(2,4),(2,3),(2,5) 1,2,3,4,5,6,7 (3,6),(3,4),(6,7),(1,2),(5,6) (1,3) 8 (1,3),(2,4),(2,3),(2,5) 1,2,3,4,5,6,7 (3,6),(3,4),(6,7),(1,2),(5,6),(1,3) (2,4) 8 (2,4),(2,3),(2,5) 1,2,3,4,5,6,7 (3,6),(3,4),(6,7),(1,2),(5,6),(1,3) (2,3) 9 (2,3),(2,5) 1,2,3,4,5,6,7 (3,6),(3,4),(6,7),(1,2),(5,6),(1,3) (2,5) 10 (2,5) 1,2,3,4,5,6,7 (3,6),(3,4),(6,7),(1,2),(5,6),(1,3) 最终生成树中边集合为
。
单源最短路径
在一个连通加权无向图
Dijkstra
迪杰斯特拉算法要求图的所有权重都是正数。维护一个优先队列(小顶堆)
求下图中各点到
的最小距离。
当前节点 已搜寻节点 最短路径数组 初始 0 0 1 0,1 7 0,1,7 6 0,1,6,7 5 0,1,5,6,7 2 0,1,2,5,6,7 8 0,1,2,5,6,7,8 3 0,1,2,3,5,6,7,8 4 0,1,2,3,4,5,6,7,8 最终各点到
的最短路径距离为 。
Bellman-Ford
贝尔曼-福特算法不要求图中边的权重都为正数,可以完成边权重为负数的最短距离求解(但如果图中出现环,且权重和小于
求下图中各点到
的最小距离。
当前节点 最短路径数组 1 2 3 4 1 2 3 4 最终各点到
的最短路径距离为 。
点对最短路径
在一个连通加权无向图
高级算法
问题分类
问题主要有验证判定问题、搜索问题、优化问题、计数问题。
0-1背包动态规划算法,暴力判定素数方法不属于多项式时间算法。
P问题:具有多项式时间算法的判定问题,可在多项式时间内求解。如素数判定、2-SAT、部分背包等。
NP问题:多项式时间内验证,不一定可解。
NPC问题:其他NP问题都可以在多项式时间内归约(符号
)到的NP问题。如3-SAT、团、顶点覆盖、独立集、旅行商(TSP)等。NPC = P NP-Hard NP-Hard问题:所有NP问题都能在多项式时间内归约到的问题,不一定是NP问题。
关系:P是NP的子集(P是否等于NP还无法判断,若相等则P等于NP等于NPC),NPC是NP的子集(NP问题不一定全能够在多项式时间内归约到P问题,取决于P是否与NP相等),NP-Hard包含NPC问题,可表示为下图。