464. 整數排序 II(排序算法)

問題

給一組整數,請將其在原地按照升序排序。使用歸併排序,快速排序,堆排序或者任何其他 O(n log n) 的排序算法。

樣例
例1:

輸入:[3,2,1,4,5],
輸出:[1,2,3,4,5]。
例2:

輸入:[2,3,1],
輸出:[1,2,3]。

快速排序

平均運行時間爲O(NlogN),最壞的運行時間爲O(N^2)
一句話總結,就是通過交換實現關鍵字左邊的元素不大於關鍵字,關鍵字右邊的元素不小於關鍵字。
快速排序利用了分治的策略。而分治的基本基本思想是:將原問題劃分爲若干與原問題類似子問題,解決這些子問題,將子問題的解組成原問題的解。
那麼如何利用分治的思想對數據進行排序呢?假如有一個元素集合A:

  • 選擇A中的任意一個元素pivot,該元素作爲基準
  • 將小於基準的元素移到左邊,大於基準的元素移到右邊(分區操作)
  • A被pivot分爲兩部分,繼續對剩下的兩部分做同樣的處理
    直到所有子集元素不再需要進行上述步驟
public class Solution {
    /**
     * @param A: an integer array
     * @return: nothing
     */

    public void sortIntegers2(int[] A) {
        
        quickSort(A, 0, A.length - 1);

    }

    private void quickSort(int[] arr, int start, int end) {
        if (start >= end)
            return;
        int left = start;
        int right = end;
        int pivot = arr[start];
        while (left <= right) {
            while (pivot < arr[right] && left <= right) {
                right--;
            }
            while (pivot > arr[left] && left <= right) {
                left++;
            }
          
            if (left <= right) {
                swap(arr, left, right);
                left++;
                right--;
            }
        }

    
        quickSort(arr, start, right);
        quickSort(arr, left, end);
    }

    private void swap(int a[], int m, int n) {
        int tmp = a[m];
        a[m] = a[n];
        a[n] = tmp;
    }

}

歸併排序

https://www.cnblogs.com/chengxiao/p/6194356.html

歸併排序(MERGE-SORT)是利用歸併的思想實現的排序方法,該算法採用經典的分治(divide-and-conquer)策略(分治法將問題分(divide)成一些小的問題然後遞歸求解,而治(conquer)的階段則將分的階段得到的各答案"修補"在一起,即分而治之)。

在這裏插入圖片描述

可以看到這種結構很像一棵完全二叉樹,本文的歸併排序我們採用遞歸去實現(也可採用迭代的方式去實現)。分階段可以理解爲就是遞歸拆分子序列的過程,遞歸深度爲log2n。
在這裏插入圖片描述
在這裏插入圖片描述

public class Solution {
    /**
     * @param A: an integer array
     * @return: nothing
     */
    public void sortIntegers2(int[] A) {
        // write your code here
        if (A == null || A.length == 0)
            return;

        // 放在外面new會比較好,這樣只需要new一次,不用次次進函數new
        int[] temp = new int[A.length];
        mergeSort(A, 0, A.length - 1, temp);
    }

    private void mergeSort(int[] A, int start, int end, int[] temp) {
        if (start >= end)
            return;

        // 無腦分治
        int mid = start + (end - start) / 2;
        mergeSort(A, start, mid, temp);
        mergeSort(A, mid + 1, end, temp);

        // 合併
        merge(A, start, end, temp);
    }

    private void merge(int[] A, int start, int end, int[] temp) {
        // 左右兩半邊數組的起始index
        int mid = start + (end - start) / 2;
        int leftIndex = start;
        int rightIndex = mid + 1;

        int index = leftIndex; // temp數組的下標

        while (leftIndex <= mid && rightIndex <= end) {
            if (A[leftIndex] < A[rightIndex])
                temp[index++] = A[leftIndex++];
            else
                temp[index++] = A[rightIndex++];
        }

        // 若是有數組還未結束,手動將之加入
        while (leftIndex <= mid)
            temp[index++] = A[leftIndex++];

        while (rightIndex <= end)
            temp[index++] = A[rightIndex++];

        // 將temp中的數字放回原數組組中
        for (int i = start; i <= end; i++)
            A[i] = temp[i];
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章