分治
几个典型的例子:MergeSort,CountingInversion,ClosestPair,Multiplication,FFT
结合随机策略:QuickSort,BFPRT and FloydRivest algorithm for Selection problem
分析:看输入是否可分 → 每个子问题的结果是否可组合
基本思想:
- 把一个问题Divide成几个独立的子问题
- 递归Conquer这些子问题
- 把子问题结果Combine起来,得到原问题解
天然可分的input结构:数组(array),矩阵(matrix),集合(set),树(tree),有向无环图(DAG)等
排序问题
问题描述:
INPUT: 包含n个整数的数组A[0...n-1]
OUTPUT: 升序排列的数组A元素
分析递归式复杂度的方法(形如T(n)的表达式):
- 展开穷举
- 猜形式并替代参数,看是否正确
- Master theorem
插入排序
MergeSort和CountingInversion(逆序数问题)
QuickSort
Selection Problem
找到第k小的元素。
方法一:排序,O(nlogn)。
方法二:QuickSelect,相比QuickSort每次只操作一个划分。O(n)。 扩展:BFPRT and FloydRivest algorithm,两种都是加入了采样策略,防止选取的pivot太差导致。
Multiplication problem
普通方法:,应用trick:
Matrix Multiplication problem
普通方法:,应用trick: (Master theorem)
ClosestPair problem
INPUT: 平面内的n个点
OUTPUT: 最短距离的两个点
普通方法:
DC:,不用y排序:
动态规划DP
几个典型的例子:MatrixChainMultiplication,Interval Scheduling(在贪心章节对比细说), Shortest Path
MatrixChainMultiplication(矩阵链式乘法)
INPUT: n个矩阵,其中矩阵Ai的维数:
OUTPUT: 乘积
矩阵(m,n)和(n,k)相乘,乘法次数:m*n*k
考虑分成独立的子问题:
- 尝试一:枚举k。要花指数多时间。发现冗余!
- 尝试二:表格法。记录下每次的值。复杂度:1 =< i,j <=n,共个OPT需要计算,外循环n次,因此
- 尝试三:不用递归,建两个表,一个OPT,一个SPLITTER,算完回溯。。
0/1背包问题
注:背包是贪心,0/1背包是DP。
INPUT:S={1,2,...,n},其中第i项带有重量wi,价值vi。背包容量W。
OUTPUT:S的子集,最大化价值。
复杂度:。W很大时效果不好,这是伪多项式时间,因为for(w=1 to W),实际上与输入长度有关。,是指数多时间。
Vertex Cover(点覆盖问题,针对树结构递归)
INPUT:一个图G=<V,E>
OUTPUT:覆盖所有边的最小点集S。
这是个NP难问题(是吧?)这里看的是树结构。
树天然可分,对每棵子树分两种情况:一,选了根节点,接着考虑子树;二,没选根节点,那么所有的子节点都要被选择,下一步考虑孙子树。
Sequence Alignment problem(序列对齐问题,针对sequence pairs结构递归)
实际问题:基因比对
INPUT:两个序列T和S,T长度m,S长度n。
OUTPUT:根据预定义的打分函数,选取最匹配的alignment方式
注:一般T是正确序列,S是偏差序列。
。(时间和空间都是)
应用DC思想:空间降低到。
扩展:banded DP,
TSP problem(在图结构上递归)
算法:Bellman-Held-Karp
SingleSourceShortestPath problem(在图结构上递归)
注:边权重可以为负,但不能有负圈
Bellman-Ford算法
OPT[v,k]表示从v到t经过最多k条边。(k<=n-1)
其实Bellman-Ford算法找到了s到任意点的最短路,以及任意点到t的最短路。
:个子问题,n次外循环(k=1 to n-1)。better analysis:,因为
扩展:检测负环。多跑几轮(令k>n),若不存在负环,则OPT[v,k]=OPT[v,n]。
条件:负环能到t。可通过扩展图实现,加一个t结点,所有点向t连一条权重为0的边。
应用:互联网路由选择。
每个路由只知道自己到下一跳的距离,是一个local问题。不能用Dijkstra求解(Dijkstra要求全局信息)!
贪心Greedy
与动态规划有关系的两个例子:SingleSourceShortestPath problem 和 IntervalScheduling problem.
其它例子:最小支撑树(SPANNING TREE)
用了贪心策略的理论:拟阵(Matroid),submodular set functions。
核心思想:local
①问题能分(多步决策) ②有最优子结构 ③(与DP不同的一点)每个子结构无需枚举,用贪心规则直接得出。
IntervalScheduling problem(区间调度问题※)
INPUT:给定n个活动A={A1,A2,...,An},需要用同一资源。每个活动Ai将在[Si , Fi)区间内需要该资源。选择Ai将带来Wi的收益。
OUTPUT:选择不冲突的活动,最大化收益。
问题细化:几个课程需要用到同一个教室。给定每堂课Ai的开始时间Si和结束时间Fi,上课人数Wi,要求让尽可能多的学生上课。
DP:
pre(i)是在Si前面结束的,Fi最大的活动index。
复杂度:需对A按结束时间排序,;共n个OPT需计算,。总体复杂度。
下面考虑一种特殊情况。所有的Wi=1。对于课程选择问题,目标由“让最多学生上课”变为了“安排最多的课程”。
贪心策略:选择最早结束的课程。
证明:设A1是最早结束的课,假设最优解,其中。由于A1结束更早,因此用A1来替换不会让解变得不可行。因此该贪心策略可行。
算法:对A按结束时间排序,选择不冲突的课即可。。
只有Wi全部为1时才能转换成贪心问题。由此提出:
Beneath every greedy algorithm, there is almost always a more cumbersome dynamic programming solution — CRLS
选取贪心规则的两个策略:
- 将一个DP方法通过贪心选择简化
- 试错。尝试多种贪心规则并作出决策。
重看ShortestPath problem
1. 无负圈: Bellman-Ford——DP
2. 无负边: Dijkstra——greedy
Dijkstra:n次插入,m次更新值,n次取最小。(用二叉堆、多项式堆)
两个策略:①每列的最小值不再更新 ②下一列的最小值一定从已扩展的点再走一步到达
Matroid
向量线性无关的性质:①遗传性质: if B is an independent vector set and A ⊂ B, then A is also an independent vector set.
②增广: if both A and B are independent vector sets, and |A| < |B|, then there is a vector v ∈ B − A such that A ∪ {v} is still an independent vector set.
在找线性无关集时,给向量组中每个向量加一个权重,问题改为求最大权重的线性无关组。
greedy:权最大的一定在最优解里。按权重排序再求即可。
发现无环森林也有这种性质!
扩展成拟阵的性质:
1. Hereditary property: if B ∈ I and A ⊂ B, then A ∈ I;
2. Augmentation property: if A ∈ I, B ∈ I, and |A| < |B|, then there is some element x ∈ B − A such that A ∪ {x} ∈ I.
Spanning Tree: an application of matroid
Kruskal’s algorithm O(m log ∗n)
Prim ,,同Dijkstra