數組旋轉

7.把一個數組最開始的若干元素搬到數組的末尾,我們稱之爲數組的旋轉。

輸入一個遞增排序數組的一個旋轉,輸出旋轉數組的最小元素。例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1.

題目信息:1.數組旋轉,有2個排好序的子數組

                 2.前面子數組元素大於等於後面子數組元素

                 3.最小元素是兩個子數組分界線

利用二分查找來實現O(logn)時間複雜度

(1)指針1指向第一個位置數字,指針2指向最後位置的數字。

(2)中間位置數字如果比指針1所指數字大,說明中間位置屬於前面的子數組,最小值在中間位置之後;如果中間位置數字比指針2所指數字大,說明中間位置屬於後面的子數組,最小值在中間位置之前。

(3)當兩指針距離爲1時,表明指針1已經在前面子數組的末尾,指針2在後面子數組的開頭,最小值就是後面子數組的第一個數字。

(4)如果兩個指針指向的數字以及中間位置數字相等時,就無法判斷屬於哪一個子數組,也就無法移動指針來縮小範圍。此時就需要採用順序查找的方法。

public class javatest {

    /**
     * @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));

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


    }
}

輸出結果:1

                1

                1

                0

                1

                2

                1



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