算法导论【时间复杂度】—排序算法、图算法、DP等小结
- 排序
- 快速排序
- 堆排序
- 计数排序
- 基数排序
- 桶排序
- SELECT算法
- RANDOMIZED-SELECT
- SELECT
- 图算法
- 广度优先搜索
- 深度优先搜索
- Kruskal算法
- Prim算法
- Bellman-Ford算法
- Dijkstra算法
- Floyd-Warshall算法
- Johnson算法
- Ford-Folkson方法
- Edmonds-Karps算法
- 动态规划
- 钢条切割
- 矩阵链乘法
- 最长公共子序列
- 最优二叉搜索树
- 字符串匹配
- 朴素算法
- Rabin-Karp
- 有限自动机
- KMP算法
排序
快速排序
- 时间复杂度:O(nlogn)
- 如果每次划分取得基准元素都是最大或者最小的元素,那么排序会退化至O(n2)
- 如何改进?
- 避免最坏的情况,使用数组中的一个随机元素作为划分元素,这样出现最坏情况的几率就会相对很小
- 取出数组的左边元素,中间元素和右边元素,然后对这三个元素进行排序,然后以中间的元素作为基准值key
堆排序
- 时间复杂度:O(nlogn),调用一次Build-Max-Heap,再循环调用Max-Heapify
- 调用Build-Max-Heap时间复杂度为O(n)
- n-1次调用Max-Heapify,每次的时间为O(logn)
计数排序
- 时间复杂度:O(n+k),实际工作中,k=O(n)时一般会采用计数排序
- n个输入都是0-k的一个整数,k=O(n)时,排序运行时间为Θ(n)
- 计数排序的基本思想是:对每一个输人元素x,确定小于x的元素个数,这样就可以直接把x放到它在输出数组中的位置上了
- 计数排序是稳定的,所以计数排序通常会被用作基数排序的一个子过程
基数排序
- 时间复杂度:O(d(n+k)),n个数每个数有d位,每个数位有k个可能的取值
- 其实就是对最高有d位数的数组,对每一位都调用计数排序一次,即进行d次计数排序
- 从最低有效位开始排序
- 为确保基数排序是正确的,一位数排序必须是稳定的
桶排序
- 时间复杂度:O(n)
- 桶排序(bucket sort)假设输入数据服从均匀分布,平均情况下它的时间代价为O(n)
- 算法还需要一个临时数组B[0… n- 1]来存放链表(即桶)
- 桶排序将[0,1)区间划分为n个相同大小的子区间,或称为桶。
- 然后,将n个输入数分别放到各个桶中。
- 因为输入数据是均匀、独立地分布在[0,1)区间上,所以一般不会出现很多数落在同一个桶中的情况。
- 为了得到输出结果,我们先对每个桶中的数进行排序,然后遍历每个桶,按照次序把各个桶中的元素列出来即可。
- 即使输入数据不服从均匀分布,桶排序也仍然可以线性时间内完成。只要输入数据满足下列性质:所有桶的大小的平方和与总的元素数呈线性关系,桶排序仍然能在线性时间完成。
SELECT算法
RANDOMIZED-SELECT
- 时间复杂度:Θ(n)
- 可以确定一个有n>1个不同元素的输入数组中第i小的元素
- 使用来自快排的确定性划分算法Partition
- 划分的基准是随机选择的,这样可以一定程度避免极端情况
- 与快排不同的是,快排会递归处理划分后的两边,而这里只处理划分的一边
- 与快排类似,若划分每次都极端的选择最大/最小元素,那时间复杂度退化至Θ(n2)
SELECT
- 时间复杂度:O(n)
- 此算法与RANDOMIZED-SELECT 类似, 区别在于该算法能保证得到对数组的一个好的划分
图算法
广度优先搜索
- 时间复杂度:O(V+E)
- Prim的最小生成树和Dijkstra的单源最短路径算法都使用了类似广度优先搜索的思想
深度优先搜索
- 时间复杂度:Θ(V+E)
Kruskal算法
- 时间复杂度:O(ElgV)
- 每次选取图中一个最小权值的边,且不构成环路
Prim算法
- 时间复杂度:O(ElgV)
- 每次选择一个最小权值边加入当前树中,且不构成环路
Bellman-Ford算法
- 时间复杂度:O(VE)
Dijkstra算法
- 时间复杂度:
- O(V2),结点编号维持最小优先队列
- O((V+E)lgV),若所有结点都可从源节点到达,则该时间为O(ElgV),二叉堆实现最小优先队列
- O(VlgV+E),斐波那契堆实现最小优先队列
Floyd-Warshall算法
- 时间复杂度:O(n3),n为顶点个数
Johnson算法
- 时间复杂度:O(V2lgV+VE)
Ford-Folkson方法
- 时间复杂度:O(E|f*|),|f*|为最大流大小
Edmonds-Karps算法
- 时间复杂度 :O(VE2),使用BFS找增广路径
动态规划
钢条切割
- 时间复杂度:O(n2)
矩阵链乘法
- 时间复杂度:O(n3)
最长公共子序列
- 时间复杂度:O(nm),两个字符串的长度分别为m,n
最优二叉搜索树
- 时间复杂度:Θ(n3)
字符串匹配
m为匹配串长度,n为文本串长度,n≥m
朴素算法
- 时间复杂度:O(m(n-m+1))
- 预处理时间:0
Rabin-Karp
- 时间复杂度:O(m(n-m+1))
- 预处理时间:Θ(m)
有限自动机
- 时间复杂度:Θ(n)
- 预处理时间:O(m|Σ|),|Σ|为字母表大小
KMP算法
- 时间复杂度:Θ(n)
- 预处理时间:Θ(m)