天天看點

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

時間複雜度O(N^2):太簡單沒啥要解釋的了

額外空間複雜度O(1):在完成每個目标的過程中,在目标完成過程中增加的變量和對象占用的空間

遞歸的深入剖析

通過一個簡單執行個體來分析:通過遞歸求一個數組中的最大值

public class GetMaxNum {
    public static int getMax(int[] arr,int L,int R){
        if (L==R){
            return arr[L];
        }
        int middle=(L+R)/2;
        int leftMax=getMax(arr,L,middle-1);
        int rightMax=getMax(arr,middle,R);
        return Math.max(leftMax,rightMax);
    }
}
           

接下來我們分析遞歸的底層是怎麼實作的

遞歸的過程就是一個系統進行一個壓棧的過程

從底層一路壓棧上去,當到達了if判斷的結束之後,系統就會進行一個出棧的過程,一步步往回出棧。

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

 總結來說:在邏輯上是自己調用自己,在系統中隻是一個系統棧而已。是以說所有的遞歸都可以變成非遞歸,也就是疊代。

master公式的詳細講解

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

T:時間複雜度

N:樣本量

以上面為例:

T(N)=a*T(N/b)+O(N^d)  --》   T(N)=2*T(N/2)+O(N^0)

T(N):指的是該算法完成某個目标所使用的所有時間;

2*T(N/2):上面程式将查詢分為左右兩邊,也就是将樣本平分了(N/2),又因為被平分了兩半是以就要乘以2 ( 2*T(N/2) ),

O(N^0):主查詢塊以外的一些消耗,這裡就是左右兩邊對比的消耗,隻進行了一次比較是以N^d=1,也就是d=0

然後帶入式子:

log(b,a):以b為底,log a

log(b,a) >d --》 log(2,2) > 0  滿足了第一個,是以上面式子的複雜度就是O(N^log(2,2))  --》  O(N)

歸并排序的深入講解

時間複雜度O(N*logN),額外空間複雜度O(N)

思想:

假設:有一個無序數組:arr=5  3  6  2  0  1

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

首先将左邊排好序,和右邊排好序

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

然後建立一個空數組,對原數組左右兩邊進行比較:

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

首先比較a和b值:a>b

放入到空數組中:

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

移動b位置

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

繼續比較a和b的值:a>b

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

移動b位置

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

 繼續比較a和b的值:a>b

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

移動b位置,發現b已經沒有了,直接拷貝a的數組

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

排序完成!

使用master公式計算:T(N)=2T(N/2)+O(N) 

log(b,a)=d,是以複雜度是N*log(N)

Coding:

将左右兩邊分别排好序

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

merge()方法

while語句中:排序的過程,如上面分析一樣,比較兩個p1和p2的值,然後指派以及移動

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

 上面while語句一定會導緻一個越界,這樣的話,就需要将另外一個沒有越界的值賦到後面

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

完整代碼

package cn.mxl.work;

public class MergeSort {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr= {4,3,2,7,6,8,0,9};
		sortProcess(arr, 0, arr.length-1);
		for(int i : arr) {
			System.out.println(i);
		}
	}
	public static void sortProcess(int[] arr,int L,int R) {
		if(L == R) {
			return ;
		}
		int mid=L+((R-L)>>1);
		sortProcess(arr,L,mid);
		sortProcess(arr,mid+1,R);
		merge(arr,L,mid,R);
	}
	private static void merge(int[] arr, int L, int mid, int R) {
		// TODO Auto-generated method stu
		int[] help=new int[R-L+1];
		int i=0;
		int p1=L;
		int p2=mid+1;
		while(p1<=mid&&p2<=R) {
			help[i++]=arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
		}
//		兩個必有且隻有一個越界
		while(p1<=mid) {
			help[i++]=arr[p1++];
		}
		while(p2<=R) {
			help[i++]=arr[p2++];
		}
		for(i=0;i<help.length;i++) {
			arr[L+i]=help[i];
		}
	}
}
           

 歸并解決小和問題

問題描述:

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

左右兩邊進行分治 ,将左邊和右邊分别排好順序

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

左邊的每個數字對于右邊排好序的來說,目前值要被加(右邊的長度-p2位置+1)次

算法的深入淺出--5.遞歸底層思想執行個體及圖解剖析以及master公式的詳細講解以及歸并排序思想與執行個體深入講解以及歸并解決小和問題

完整代碼:

public class SmallSum {
    public static int partitionSort(int[] arr,int L,int R){
        if (L==R){
            return 0;
        }
        int middle=L+((R-L)>>1);
        return partitionSort(arr,L,middle)
                +partitionSort(arr,middle+1,R)
                +merge(arr,L,middle,R);
    }

    private static int merge(int[] arr, int l, int middle, int r) {
        int pos1=l;
        int pos2=middle+1;
        int[] help=new int[r-l+1];
        int i=0;
        int res=0;
        while (pos1<=middle && pos2<=r){
            res+=arr[pos1]<arr[pos2]?(r-pos2+1)*arr[pos1]:0;
            help[i++]=arr[pos1]<arr[pos2]?arr[pos1++]:arr[pos2++];
        }
        while (pos1<=middle){
            help[i++]=arr[pos1++];
        }
        while ((pos2<=r)){
            help[i++]=arr[pos2++];
        }
        for (int j = 0; j < help.length; j++) {
            arr[l+j]=help[j];
        }
        return res;
    }

    public static void main(String[] args){
        int[] arr={1,3,4,2,5};
        int res = partitionSort(arr, 0, arr.length - 1);
        System.out.println(res);
    }
}
           

繼續閱讀