1. 程式人生 > >劍指offer{面試題8:旋轉陣列的最小數字}

劍指offer{面試題8:旋轉陣列的最小數字}

思路:還是設定兩個指標,一頭一尾,隨時變動指標,左半部分大指標往中間去,右半部分大指標前移, public class test08 {

    /**
     * 把一個數組最開始的若干個元素搬到陣列的末尾, 我們稱之陣列的旋轉。
     * 輸入一個遞增排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。
     * 例如陣列{3, 4, 5, 1, 2}為{l ,2, 3, 4, 5}的一個旋轉,該陣列的最小值為
     *
     * @param numbers 旋轉陣列
     * @return 陣列的最小值
     */
    public static int min(int[] numbers) {
        // 判斷輸入是否合法
        if (numbers == null || numbers.length == 0) {
            throw new RuntimeException("Invalid input.");
        }

        // 開始處理的第一個位置
        int lo = 0;
        // 開始處理的最後一個位置
        int hi = numbers.length - 1;
        // 設定初始值
        int mi = lo;

        // 確保lo在前一個排好序的部分,hi在排好序的後一個部分
        while (numbers[lo] >= numbers[hi]) {
            // 當處理範圍只有兩個資料時,返回後一個結果
            // 因為numbers[lo] >= numbers[hi]總是成立,後一個結果對應的是最小的值
            if (hi - lo == 1) {
                return numbers[hi];
            }

            // 取中間的位置
            mi = lo + (hi - lo) / 2;

            // 如果三個數都相等,則需要進行順序處理,從頭到尾找最小的值
            if (numbers[mi] == numbers[lo] && numbers[hi] == numbers[mi]) {
                return minInorder(numbers, lo, hi);
            }

            // 如果中間位置對應的值在前一個排好序的部分,將lo設定為新的處理位置
            if (numbers[mi] >= numbers[lo]) {
                lo = mi;
            }
            // 如果中間位置對應的值在後一個排好序的部分,將hi設定為新的處理位置
            else if (numbers[mi] <= numbers[hi]) {
                hi = mi;
            }
        }

        // 返回最終的處理結果
        return numbers[mi];
    }

    /**
     * 找陣列中的最小值
     *
     * @param numbers 陣列
     * @param start   陣列的起始位置
     * @param end     陣列的結束位置
     * @return 找到的最小的數
     */
    public static int minInorder(int[] numbers, int start, int end) {
        int result = numbers[start];
        for (int i = start + 1; i <= end; i++) {
            if (result > numbers[i]) {
                result = numbers[i];
            }
        }
        return result;
    }


    public static void main(String[] args) {
        // 典型輸入,單調升序的陣列的一個旋轉
        int[] array1 = {3, 4, 5, 1, 2};
        System.out.println(min(array1));

        // 有重複數字,並且重複的數字剛好的最小的數字
        int[] array2 = {3, 4, 5, 1, 1, 2};
        System.out.println(min(array2));

        // 有重複數字,但重複的數字不是第一個數字和最後一個數字
        int[] array3 = {3, 4, 5, 1, 2, 2};
        System.out.println(min(array3));

        // 有重複的數字,並且重複的數字剛好是第一個數字和最後一個數字
        int[] array4 = {1, 0, 1, 1, 1};
        System.out.println(min(array4));

        // 單調升序陣列,旋轉0個元素,也就是單調升序陣列本身
        int[] array5 = {1, 2, 3, 4, 5};
        System.out.println(min(array5));

        // 陣列中只有一個數字
        int[] array6 = {2};
        System.out.println(min(array6));

        // 陣列中數字都相同
        int[] array7 = {1, 1, 1, 1, 1, 1, 1};
        System.out.println(min(array7));
        System.out.println(min(array6));

        // 輸入NULL
        System.out.println(min(null));


    }
}