《算法》第二章——生成快排的最佳序列

題目:

Best case. Write a program QuickBest.java that produces a best-case array (with no duplicates) for Quick.sort(): an array of N distinct keys with the property that every partition will produce subarrays that differ in size by at most 1 (the same subarray sizes that would happen for an array of N equal keys). For the purposes of this exercise, ignore the initial shuffle.

思路:

對於一個無序序列,使得快速排序效率最高的序列的特點是:

pivort lower-ones bigger-ones 

代碼:

public class QuickBest {

    // postcondition: a[lo..hi] is best-case input for quicksorting that subarray
    private static void best(int[] a, int lo, int hi) {

        // precondition:  a[lo..hi] contains keys lo to hi, in order
        for (int i = lo; i <= hi; i++)
            assert a[i] == i;

        if (hi <= lo) return;
        int mid = lo + (hi - lo) / 2;
        best(a, lo, mid-1);
        best(a, mid+1, hi);
        exch(a, lo, mid);
    }

    public static int[] best(int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; i++)
            a[i] = i;
        best(a, 0, n-1);
        return a;
    }

    // exchange a[i] and a[j]
    private static void exch(int[] a, int i, int j) {
        int swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }


    public static void main(String[] args) {
        String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        int n = Integer.parseInt(args[0]);
        int[] a = best(n);
        for (int i = 0; i < n; i++)
            // StdOut.println(a[i]);
            StdOut.print(alphabet.charAt(a[i]));
        StdOut.println();
    }
}

體會:

用遞歸處理問題時感覺有兩個難點。
1.如何劃分子問題。
2.對子問題的處理語句應該放在遞歸調用語句的前面還是後面。比如:上面exch()就放在best()的後面。
假設初始序列是1,2,3,4,5,6,7.此時mid爲4。
(1)如果先best()再exch(),那麼這種方法的子問題就是1,2,3和5,6,7。
(2)如果先exch()再best(),那麼這種方法的子問題就是2,3,1和5,6,7。可見由於先執行了exch操作導致子問題2,3,1不再有序。
於是根據這個我偏向於選擇(1)。

另外,考慮快排的原理。快排是先partition再sort遞歸,在partiton過程中進行了lo和mid的交換。而本題相當於快排的一個逆過程。應該先將小問題的交換處理完在進行大問題的交換操作。
於是根據這個我偏向於選擇(1)。

對應問題2,假設處理子問題的函數是hanle(),如果處理當前問題的前提是要先處理該問題的子問題那麼就要將handle放在遞歸函數後面。否則就是一handle當前函數的方式handle該問題的子問題。

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