分治算法定义
将一个问题分解成多个子问题,将问题缩小到一定规模后逐个求解,最后合并所有子问题
分治算法步骤
- 分解(将原问题分解成一个形式相同规模更小的子问题)
- 解决(递归求解子问题,直到问题的规模足够小,直接求解)
- 合并(合并子问题的解,得到原问题的解)
分治算法例题(实际应用)
插入排序
思路
一道十分普通的 O ( n 2 ) O(n^2) O(n2)时间复杂度题,使用类似打扑克牌时给牌排序的分治思想递归实现即可
即:
先给n-1张牌排序,再分成给n-2张牌排序,以此类推…
直到只剩1张牌,则直接结束
Code
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a[110]; 4 void insert_sort(int a[],int n){ 5 //1.基本情况 6 if(n==1)return; 7 //2.分解子问题 8 //3.解决子问题 9 insert_sort(a,n-1); 10 int tmp=a[n],i; 11 for(i=n-1;i>=1;i--){ 12 if(a[i]>tmp){ 13 a[i+1]=a[i]; 14 }else{ 15 break; 16 } 17 } 18 a[i+1]=tmp; 19 } 20 int main(){ 21 scanf("%d",&n); 22 for(int i=1;i<=n;i++){ 23 scanf("%d",&a[i]); 24 } 25 insert_sort(a,n); 26 for(int i=1;i<=n;i++){ 27 printf("%d ",a[i]); 28 } 29 return 0; 30 }
归并排序
思路
这道题的数据范围加大,不能再用 O ( n 2 ) O(n^2) O(n2)算法解决,会导致TLE;故我们可以用归并排序解决
Code
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a[110],b[110]; 4 void merge(int a[],int l,int mid,int r,int t[]){ 5 int i=l,j=mid+1,k=l; 6 while(i<=mid&&j<=r){ 7 if(a[i]<=a[j])t[k++]=a[i++]; 8 else t[k++]=a[j++]; 9 } 10 while(i<=mid)t[k++]=a[i++]; 11 while(j<=r)t[k++]=a[j++]; 12 for(i=l;i<=r;i++)a[i]=t[i]; 13 } 14 void merge_sort(int a[],int l,int r,int t[]){ 15 //1.基本情况 16 if(l==r)return; 17 //2.分解子问题 18 int mid=(l+r)>>1; 19 //3.解决子问题 20 merge_sort(a,l,mid,t); 21 merge_sort(a,mid+1,r,t); 22 //4.合并子问题的解 23 merge(a,l,mid,r,t); 24 } 25 int main(){ 26 scanf("%d",&n); 27 for(int i=1;i<=n;i++){ 28 scanf("%d",&a[i]); 29 } 30 merge_sort(a,1,n,b); 31 for(int i=1;i<=n;i++){ 32 printf("%d ",a[i]); 33 } 34 return 0; 35 }
快速排序
思路
使用 O ( n log n ) O(n log n) O(nlogn)时间复杂度的快速排序,具体步骤看下图
Code
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a[100010]; 4 void quick_sort(int a[],int l,int r){ 5 //1.基本情况 6 if(l==r)return;//可省略 7 //2.分解子问题 8 int i=l,j=r,mid=a[l+rand()%(r-l+1)]; 9 while(i<=j){ 10 while(a[i]<mid)i++; 11 while(a[j]>mid)j--; 12 if(i<=j){ 13 swap(a[i],a[j]); 14 i++; 15 j--; 16 } 17 } 18 //3.解决子问题 19 if(l<j)quick_sort(a,l,j); 20 if(i<r)quick_sort(a,i,r); 21 //4.合并子问题的解 22 } 23 int main(){ 24 scanf("%d",&n); 25 for(int i=1;i<=n;i++){ 26 scanf("%d",&a[i]); 27 } 28 quick_sort(a,1,n); 29 for(int i=1;i<=n;i++){ 30 printf("%d ",a[i]); 31 } 32 return 0; 33 }