基本思想:
一个规模为n的问题可以分解为多个规模较小的子问题,每个子问题相互独立,且与原问题相同,最后将子问题的解合并可得原问题的解。
复杂度分析:
二分查找
int bi_search(int a[],int l,int r,int x)
{
while(l<r)
{
int mid=l+r>>1;
if(a[mid]>=x)r=mid;
else l=mid+1;
}
if(a[l]==x)return l;
return -1;
}
T(n)=T(n/2)+O(1)=O(logn)
幂乘问题
int power(int x,int n)
{
if(n==1)return x;
int ans,t;
if(n%2)ans=x,t=power(x,n-1>>1);
else ans=1,t=power(x,n>>1);
return ans*t*t;
}
T(n)=T(n/2)+O(1)=O(logn)
大整数乘法
Strassen矩阵乘法
棋盘覆盖
void chess_board(int tr,int tc,int dr,int dc,int size)
{
if(size==1)return;
int t=ans++;
int s=size>>1;
if(dr<tr+s&&dc<tc+s)chess_board(tr,tc,dr,dc,s);
else board[tr+s-1][tc+s-1]=t,chess_board(tr,tc,tr+s-1,tc+s-1,s);
if(dr<tr+s&&dc>=tc+s)chess_board(tr,tc+s,dr,dc,s);
else board[tr+s-1][tc+s]=t,chess_board(tr,tc+s,tr+s-1,tc+s,s);
if(dr>=tr+s&&dc<tc+s)chess_board(tr+s,tc,dr,dc,s);
else board[tr+s][tc+s-1]=t,chess_board(tr+s,tc,tr+s,tc+s-1,s);
if(dr>=tr+s&&dc>=tc+s)chess_board(tr+s,tc+s,dr,dc,s);
else board[tr+s][tc+s]=t,chess_board(tr+s,tc+s,tr+s,tc+s,s);
}
T(n)=4T(n/4)+O(1)=O(n)=(2^k*2^k)=O(4^k)
快排
void quick_sort(int l,int r)
{
if(l>=r)return;
int i=l,j=r+1;
while(1)
{
while(a[++i]<a[l]&&i<=r);
while(a[--j]>a[l]);
if(i>=j)break;
swap(a[i],a[j]);
}
swap(a[l],a[j]);
quick_sort(l,j-1),quick_sort(j+1,r); //or j,j+1
}
归并排序
void merge_sort(int l,int r)
{
if(l>=r)return;
int mid=l+r>>1;
merge_sort(l,mid),merge_sort(mid+1,r);
int p1=l,p2=mid+1,p3=l;
while(p1<=mid&&p2<=r)
{
if(a[p1]<a[p2])temp[p3++]=a[p1++];
else temp[p3++]=a[p2++];
}
while(p1<=mid)temp[p3++]=a[p1++];
while(p2<=r)temp[p3++]=a[p2++];
for(int i=l;i<=r;++i)a[i]=temp[i];
}
T(n)=2T(n/2)+O(n)=O(nlogn)
查找第k小
int kmin(int a[],int l,int r,int k)
{
if(r-l<=75)
{
sort(a+l,a+r+1);
return a[l+k-1];
}
for(int i=0;i<=(r-l-4)/5;++i) //取中位数
{
sort(a+l+5*i,a+l+5*(i+1));
swap(a[l+5*i+2],a[l+i]);
}
int x=kmin(l,l+(r-l-4)/5,(r-l-4)/10+1); //取中位数的中位数
int i=l-1,j=r+1; //划分区间
while(1)
{
while(a[++i]<x);
while(a[--j]>x);
if(i>=j)break;
swap(a[i],a[j]);
}
i=j-l+1;
if(k<=i)return kmin(l,j,k);
else return kmin(j+1,r,k-i);
}
一维最近点对
平面最近点对,见ppt