1. 程式人生 > 實用技巧 >洛谷-P4414 [COCI2006-2007#2] ABC

洛谷-P4414 [COCI2006-2007#2] ABC

核心思想:

1、選取一個左邊第一個元素為基數,從兩頭遍歷集合( i、j 分別從兩端索引)

2、i 索引大於 基數的 值,j 索引小於 基數的值 (j 先索引,然後 i 索引,當遇到符合的條件時停止索引)

3、交換兩個索引的數值,然後繼續索引

4、當 i 與 j 相遇時 結束當前索引

5、將基數所在位置與 i,j 所索引位置的值進行交換

6、遞迴呼叫兩端的集合

快速排序的時間複雜度為O(log2N)

package com.jason.sort;

/**
 * @program: LeetCode
 * @description: 快速排序
 * @author: CodeDuck
 * @create: 2020-07-17 20:23
 **/
public class QuickSort {

    public static void main(String[] args) {
        int[] arr = {6, 7, 18, 3, 5, 4, 10, 9};
        quickSort(arr);
        for (int a : arr) {
            System.out.println(a);
        }
    }

    public static void quickSort(int[] arr) {
        quickSort(arr, 0, arr.length - 1);
    }

    /**
     * @Description: 快速排序
     * @Param: int[] 陣列
     */
    private static void quickSort(int[] arr, int left, int right) {

        if (left >= right) {    // 當滿足條件時結束當前遞迴
            return;
        }

        int i = left;   // 左索引
        int j = right;  // 右索引

        // 從陣列的最左端開始,選取基準數
        int baseNum = arr[left];

        // 關於為什麼是 右邊的 J 先走問題
        // 此排序為升序排序,如果 I 先走,走到最後與J相遇是主動跑到J位置上
        // 此時的數是大於基數的,不能將此數同基數交換
        while (i < j) {
            while (arr[j] >= baseNum && i < j) {    // 從右至左選擇小於基數的數
                j--;
            }
            while (arr[i] <= baseNum && i < j) {    // 從左至右選擇大於基數的數
                i++;
            }

            if (i < j) {
                swap(arr, i, j);                    // 交換兩個數值
            }
        }

        arr[left] = arr[i];                         // 將當前i與j相遇的值與技術交換
        arr[i] = baseNum;

        quickSort(arr, left, i - 1);            // 遞迴呼叫基數左邊的集合
        quickSort(arr, i + 1, right);            // 遞迴呼叫基數右邊的集合

    }

    /**
     * @Description: 交換元素
     * @Param: arr 元素組
     * @Param: i,j陣列下標
     * @return: void
     */
    private static void swap(int[] arr, int i, int j) {

        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}