introduction
the master method
T(n) = aT(n/b)+f(n)<其中a>=1,b>1,f(n)为渐近正函数>
f(n) = O(n<sup>log<sub>b</sub>a-ε</sup>),T(n)=O(n<sup>log<sub>b</sub>a</sup>)
f(n) = O(n<sup>log<sub>b</sub>a</sup>\*log<sup>k</sup>n),T(n)=O(f(n)\*logn)
f(n) = O(n<sup>log<sub>b</sub>a+ε</sup>),T(n)=O(f(n))
divide and conquer
Tower of Hanoi
code
hanoi(n-1,A,C,B); move(n,A,B); hanoi(n-1,C,B,A);
time complexity:
M(1)=1
M(n)=2M(n-1)+1=2[2M(n-2)+1]+1=2n-1
O(n)=2n
MergeSort
recursion
mergesort(left,right,**a){ if(left<right){ int mid = 1/2(left+right); mergesort(left,mid,**a); mergesort(mid+1,right,**a); merge(a,b,left,right); copy(a,b,left,right); } }
nonrecursion
void merge_sort(int *list, int length){ int i, left_min, left_max, right_min, right_max, next; int *tmp = (int*)malloc(sizeof(int) * length); for(i=1;i<length;i*=2){ right_min = left_max = left_min+i; right_max = left_max+i; if(right_max>length){ right_max = length; } next = 0; while(left_min<left_max&&right_min<right_max){ tmp[next++] = list[left_min]>list[right_min]? list[right_min++]:list[left_min++]; } while(left_min < left_max){ list[--right_min] = list[--left_max]; } while(next>0){ list[--right_min] = tmp[--next]; } } }
time complexity:
T(n)=2T(n/2)+cn
O(nlogn)space complexity:
O(n)
Strassen’s matrix multiplication
the divide and conquer of matrix
T(n) = 8(T(n/2))+O(n<sup>2</sup>)
QuickSort
code
int Partition(Type a[],int p,int r){ int j=p; int j=r+1; Type x=a[p]; while(true){ while(a[++i]<x&&i<j); while(a[--j]>x&&i<j); if(i=j) break; swap(a[i],a[j]); a[p]=a[j]; a[j]=x; return j; } } void quiclSort(Type a[],int p,int r){ if(p<r){ int q=Partition(a,p,r); quickSort(a,p,q-1); quickSort(a,q+1,r); } }
time complexity:
Best case: split in the middle — Θ(nlogn)
Worst case: sorted array! — Θ( n2)
Average case: random arrays — Θ(nlogn)
linear time selection
- 只要不是选到了首尾,O(n)
Dynamic Programming
Fibonacci series
+ ![](/Users/za/Desktop/doc/斐波那契数列通项公式.png)
Matrix-chain Multiplication
code
void MatrixChain(){ int p[6] = {20,25,10,5,15,20}; int n = 5; int m[10][10]; int s[10][10]; int j = 0; for (int i=1; i<=n; i++){ m[i][i]=0; };//单个矩阵的计算量 for (int r=2; r<=n; r++){//r为每次循环矩阵链的长度 for (int i=1; i<=n-r+1; i++){ j=i+r-1; //设置初始值为从第一个元素进行断开 m[i][j]= m[i+1][j] + p[i-1]*p[i]*p[j]; //设置初始断开位置 s[i][j]=i; for (int k=i+1; k<j; k++){ //当前k值计算得到的值 int t= m[i][k]+ m[k+1][j]+p[i-1]*p[k]*p[j]; /*替换找到最小值*/ if (t< m[i][j]) { m[i][j]=t; s[i][j]=k; } } } } }
analysis
- 分析最优解结构:M(1,n)=M(1,k)+M(k+1,n)+P0PkPn
(P0PkPn类型为两个矩阵相乘所需的计算步骤) - 1.初始化矩阵链的对角线位置元素
M[a][a]=0
- 2.确定矩阵链长度
for(r=2;r<n+1;r++)
- 3.用i表示起始位置,j表示终止位置
for(i=1;i<n+1-r;i++),j=i+r-1
- 4.M(i,j)=M(i,k)+M(k+1,j)+PiPjPk,循环k的值
for(k=i+1;k<j;k++)
→找到最大值,并将k的值记录下来,存储到**t中
- 分析最优解结构:M(1,n)=M(1,k)+M(k+1,n)+P0PkPn
0-1 Knapsack Problem
code
void KnapSack(){ int w[4] = {2,1,3,2};//物品重量 int v[4] = {12,10,20,15};//物品价值 int c = 5;//背包容量 int n = 4;//物品个数 int m[c][n];//初始化矩阵 int jMax = 0; if(w[n]-1>c){ jMax=c; }else{ jMax=w[n]-1; } //使刚开始到最小容量的值直接为0 for(int j=0;j<=jMax;j++){ m[n][j] = 0; } for (int j=w[n]; j<c; j++) { m[n][j] = v[n]; } for(int i=n-1; i>1; i--) { jMax = min(w[i]-1,c); //装不下第i个物品的,直接继承i+1的值 for(int j=0; j<=jMax; j++){ m[i][j] = m[i+1][j]; } for(int j=w[i];j<=c;j++){ m[i][j] = max(m[i+1][j],m[i+1][j-w[i]+v[i]); } } //最后的结果行不用计算之前复杂项了 m[1][c] = m[2][c]; if(c>=w[1]){ m[1][c]=max(m[1][c],m[2][c-w[1]]+v[1]); } } //判断i和i+1的值相等否可以得出是否放了这个物品 Template<class Type> Void Traceback(Type **m,int w,int c,int n,int x) { for(int i=1;i<n;i++) if(m[i][c]==m[i+1][c]){ x[i]=0; }else{ x[i]=1; c-=w[i]; } x[n]=(m[n][c])?1:0; }
analysis
- m[i][j] = max(m[i+1][j],m[i+1][j-w[i]+v[i]]);
- 判定m(i,c)与m(i+1,c)的值是否相等来确定x(i+1)是否为1;
Optimal Binary Search Trees
binary search tree
e[i,j] = min(e[i,r-1]+e[r+1,j]+w(i,j))
Greedy Algorithms
Backtracking
Loading Problem
analysis
按深度优先先进行一条线路的遍历,到达底部后重新回溯生成最优解,进行比较到最后生成最后的解
0-1 knapsack problem
analysis
最优解的限界为装入尽可能多的物品,并且将最后一部分物品只装入部分产生的限界.
time complexity
O(n2n)
Graph m coloring problem
Branch and bound(在约束条件下找出一个最优解)
Loading Problem
code
if(Ew+w[i]<=c){ AddLiveNode(H,E,Ew+w[i]+r[i],true,i+1); } AddLiveNode(H, E, Ew+r[i], false, i+1); HeapNode<Type> N; H.DeletMax(N); i = N.level; E = N.ptr; Ew = N. uweight – r[ i -1 ];
anlysis
节点的左子树表示将此集装箱装上船,右子树表示不将此集装箱装上船。
设bestw是当前最优解;Ew是当前扩展结点所相应的重量;r是剩余集装箱的重量。
则当Ew+r≤bestw时,可将其右子树剪去,因为此时若要船装最多集装箱,就应该把此箱装上船。