《劍指offer第二版》題11:旋轉(zhuǎn)數(shù)組的最小數(shù)字

題目:把一個數(shù)組最開始的若干個元素搬到數(shù)組的末尾, 我們稱之數(shù)組的旋轉(zhuǎn)。輸入一個遞增排序的數(shù)組的一個旋轉(zhuǎn), 輸出旋轉(zhuǎn)數(shù)組的最小元素。例如數(shù)組{3,4,5,1,2 }為{1,2,3,4,5}的一個旋轉(zhuǎn),該數(shù)組的最小值為1。

最直接的解法:從頭到尾遍歷數(shù)組查找。時間復雜度O(n)。但是這種思路沒有利用旋轉(zhuǎn)數(shù)組的特性。

public int minArray(int[] numbers) {
    if (numbers == null) {
        //注意:我們假設(shè)`-5000 <= numbers[i] <= 5000`,
        return -5001;
    }
    if (numbers.length == 1) {
        return numbers[0];
    }
    int lastIndex = numbers.length;
    int index = 0;
    for (int i = 0; i < lastIndex - 1; i++) {
        if (numbers[i] > numbers[i + 1]) {
            index = i + 1;
            break;
        }
    }
    return numbers[index];
}

第二種解法

旋轉(zhuǎn)后的數(shù)組實際上可以劃分為兩個排序的子數(shù)組,而且前面子數(shù)組的元素都大于或者等于后面子數(shù)組的元素。我們還注意到最小元素剛好是這兩個子數(shù)組的分界線。在排序的數(shù)組中我們可以用二分查找法實現(xiàn)O(logn)的查找。本題給出的數(shù)組在一定程度上是排序的,因此可以試著用二分查找的思路來尋找最小元素。

     private static int min(int[] numbers) {
        if (numbers == null || numbers.length == 0) {
            throw new IllegalArgumentException("Invalid input.");
        }
        int low = 0;
        int high = numbers.length - 1;
        //設(shè)置初始值
        int mid = low;
        while (numbers[low] >= numbers[high]) {
            if (high - low == 1) {
                mid = high;
                break;
            }
            mid = (low + high) / 2;
            //注釋1處,如果三個數(shù)都相等,則需要進行順序查找
            if (numbers[mid] == numbers[low] && numbers[mid] == numbers[high]) {
                return minInOrder(numbers, low, high);
            }
            if (numbers[mid] >= numbers[low]) {
                low = mid;
            } else if (numbers[mid] <= numbers[high]) {
                high = mid;
            }
        }
        return numbers[mid];
    }

    /**
     * 順序查找
     *
     * @param numbers
     * @param low
     * @param high
     * @return
     */
    private static int minInOrder(int[] numbers, int low, int high) {
        int result = numbers[low];
        for (int i = low + 1; i <= high; i++) {
            if (result > numbers[i]) {
                result = numbers[i];
            }
        }
        return result;
    }

注釋1處,如果三個數(shù)都相等,則需要進行順序查找,這三個數(shù)不是連著的,可能是如下:

int[] array = {3,3,1,3};

第一次進來,low = 0 ,high =3 ,mid = 1
array[0] = array[1] = array[3] ,這個時候就要順序查找。

測試用例

    public static void main(String[] args) {

        // 旋轉(zhuǎn)0個元素
        int[] array0 = {1, 2, 3, 4, 5};
        System.out.println(min(array0));

        int[] array1 = {3, 4, 5, 1, 2};
        System.out.println(min(array1));

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

        // 有重復數(shù)字
        int[] array3 = {3, 4, 5, 1, 2, 2};
        System.out.println(min(array3));

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

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

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

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

    }

參考鏈接:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容