partition、快排和隨機快排

做了《劍指offer》中最小的k個數的題目(詳情可見這篇博客https://blog.csdn.net/weixin_42582008/article/details/100937950 )

和數組中出現次數超過一半的數字的題目(詳情可見這篇博客https://blog.csdn.net/weixin_42582008/article/details/100760644

都可以用partition解決,雖然都不是最佳解法。但感覺自己對partition的過程不是很瞭解,就回顧了一下partition和快速排序。

1.partition

partition可以將數組分爲三部分,假如選定最後一個數字temp作爲基準,那麼從左向右分別爲小於temp的部分,等於temp的部分,大於temp的部分。一般情況下,爲了簡單起見,不需要將大於temp的數和等於temp的數分開處理(但還是數組還是劃分爲三部分,只不過第二部分只是一個數,其他和temp相等的數和大於temp的數一樣處理)partition函數如下所示,這對於處理“求第k小的元素這種問題是沒有問題的,這樣做快排也沒問題)


    public int partition(int[] array,int start,int end){
        int temp = array[end];
        int less = start-1;
       for(int i=start;i<end;i++){
           if(array[i]<temp){
               swap(array,++less,i);
           }
       }
       swap(array,++less,end);
       return less;

但是也可以嚴格分爲三部分,第二部分不是一個數,而是所有和temp相等的數(當然,如果只有一個,那麼也是一個數)。partition代碼如下所示,下標小於等於less的數爲小於temp的,下標大於等於more的數爲大於temp的,之間的數爲等於temp的.從start開始遍歷數組,如果遍歷到的元素和temp相等,什麼都不做,繼續遍歷下一個,如果小於temp,那麼和less之後的數交換,less=less+1,繼續遍歷下一個數,如果大於temp,那麼和more之前的數交換,more=more-1,這時start不能加1,因爲不知道交換過來的數和temp的大小關係。直到start=more,遍歷結束。將end上的數和more位置的數交換,more=more+1。返回的less和more滿足下標小於等於less的數爲小於temp的,下標大於等於more的數爲大於temp的,之間的數爲等於temp。partiton過程結束。

public static int[] partition(int[] arr, int start, int end) {
        int less = start - 1;
        int more = end;
        int temp = arr[end];
        while (start<more){
            if (arr[start] < temp) {
                swap(arr, ++less, start++);
            } else if (arr[start] > temp) {
                swap(arr, --more, start);
            }else{
                start++;
            }

        }
        swap(arr,more++,end);
        return new int[] {less,more};
    }

2.快排與隨機快排

partition過程明瞭了,快排也就簡單了 ,只需要將數組進行一次partition,再將第一和第三部分再進行quickSort,注意退出遞歸的條件就可以了。之所以有隨機快排,是因爲,普通快排再數組有序時,時間複雜度爲O(n^2),而隨機快排可以不只是以end位置的數爲基準,可以在有序的情況下時間複雜度仍爲O(nlogn)。隨機快排和快排差別只在於有無這句代碼,即是否在partition前將end位置的數與[start,end]位置上隨機的一個的數交換一下。

swap(arr,(int)(start+Math.random()*(end-start+1)),end);

完整快排代碼: 

import java.util.Arrays;

public class JustTry {
    public static void main(String[] args) {
        //隨便寫的一個測試用例
        int[] input = {2,3,1,43,1,434,1,43,14,1,2,34,4,5,56,56};
        quickSort(input,0,input.length-1);
        System.out.println(Arrays.toString(input));
    }

    public static void quickSort(int[] arr){
        if(arr == null || arr.length<2){
            return;
        }
        quickSort(arr,0,arr.length-1);
    }

    public static void quickSort(int[] arr, int start, int end) {
        if (arr == null || arr.length < 2 || start >= end) {
            return;
        }
        //有下面這段代碼,爲隨機快排,否則爲普通快排,(int)(start+Math.random()*(end-start+1))產生一個[start,end]的隨機數
        swap(arr,(int)(start+Math.random()*(end-start+1)),end);
        int[] index = partition(arr, start, end);
        quickSort(arr, start, index[0]);
        quickSort(arr, index[1], end);
    }

    public static int[] partition(int[] arr, int start, int end) {
        int less = start - 1;
        int more = end;
        int temp = arr[end];
        while (start<more){
            if (arr[start] < temp) {
                swap(arr, ++less, start++);
            } else if (arr[start] > temp) {
                swap(arr, --more, start);
            }else{
                start++;
            }

        }
        swap(arr,more++,end);
        return new int[] {less,more};
    }


    public static void swap(int[] arr ,int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章