zoukankan      html  css  js  c++  java
  • 分治算法总结

    分治算法定义

    将一个问题分解成多个子问题,将问题缩小到一定规模后逐个求解,最后合并所有子问题

    分治算法步骤

    1. 分解(将原问题分解成一个形式相同规模更小的子问题)
    2. 解决(递归求解子问题,直到问题的规模足够小,直接求解)
    3. 合并(合并子问题的解,得到原问题的解)

    分治算法例题(实际应用)

    插入排序

    思路

    一道十分普通的(O(n^2))时间复杂度题,使用类似打扑克牌时给牌排序的分治思想递归实现即可

    即:

    先给n-1张牌排序,再分成给n-2张牌排序,以此类推.......

    直到只剩1张牌,则直接结束

    (Code)

    #include<bits/stdc++.h>
    using namespace std;
    int n,a[110];
    void insert_sort(int a[],int n){
    	//1.基本情况 
    	if(n==1)return;
    	//2.分解子问题 
    	//3.解决子问题 
    	insert_sort(a,n-1);
    	int tmp=a[n],i; 
    	for(i=n-1;i>=1;i--){
    		if(a[i]>tmp){
    			a[i+1]=a[i];
    		}else{
    			break;
    		}
    	}
    	a[i+1]=tmp;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    	}
    	insert_sort(a,n);
    	for(int i=1;i<=n;i++){
    		printf("%d ",a[i]);
    	}
    	return 0;
    }
    

    归并排序

    思路

    这道题的数据范围加大,不能再用(O(n^2))算法解决,会导致TLE;故我们可以用归并排序解决

    图解

    (Code)

    #include<bits/stdc++.h>
    using namespace std;
    int n,a[110],b[110];
    void merge(int a[],int l,int mid,int r,int t[]){
    	int i=l,j=mid+1,k=l;
    	while(i<=mid&&j<=r){
    		if(a[i]<=a[j])t[k++]=a[i++];
    		else t[k++]=a[j++];
    	}
    	while(i<=mid)t[k++]=a[i++];
    	while(j<=r)t[k++]=a[j++];
    	for(i=l;i<=r;i++)a[i]=t[i];
    }
    void merge_sort(int a[],int l,int r,int t[]){
    	//1.基本情况 
    	if(l==r)return;
    	//2.分解子问题 
    	int mid=(l+r)>>1;
    	//3.解决子问题 
    	merge_sort(a,l,mid,t);
    	merge_sort(a,mid+1,r,t);
    	//4.合并子问题的解 
    	merge(a,l,mid,r,t);
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    	}
    	merge_sort(a,1,n,b);
    	for(int i=1;i<=n;i++){
    		printf("%d ",a[i]);
    	}
    	return 0;
    }
    

    快速排序

    思路

    使用(O(n log n))时间复杂度的快速排序,具体步骤看下图

    (Code)

    #include<bits/stdc++.h>
    using namespace std;
    int n,a[100010];
    void quick_sort(int a[],int l,int r){
    	//1.基本情况 
    	if(l==r)return;//可省略
    	//2.分解子问题 
    	int i=l,j=r,mid=a[l+rand()%(r-l+1)];
    	while(i<=j){
    		while(a[i]<mid)i++;
    		while(a[j]>mid)j--;
    		if(i<=j){
    			swap(a[i],a[j]);
    			i++;
    			j--;
    		}
    	}
    	//3.解决子问题 
    	if(l<j)quick_sort(a,l,j);
    	if(i<r)quick_sort(a,i,r);
    	//4.合并子问题的解 
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    	}
    	quick_sort(a,1,n);
    	for(int i=1;i<=n;i++){
    		printf("%d ",a[i]);
    	}
    	return 0;
    }
    
    她透过我的血,看到了另一抹殷红
  • 相关阅读:
    Find the Smallest K Elements in an Array
    Count of Smaller Number
    Number of Inversion Couple
    Delete False Elements
    Sort Array
    Tree Diameter
    Segment Tree Implementation
    Java Programming Mock Tests
    zz Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)
    Algorithm about SubArrays & SubStrings
  • 原文地址:https://www.cnblogs.com/zhangbeini/p/13617359.html
Copyright © 2011-2022 走看看