劍指offer--旋轉數組的最小數字

題目描述

把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。 輸入一個非減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。 NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。

解法分析

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        if(array == null || array.length == 0)
            return 0;
        int p1 = 0, p2 = array.length-1;
        //也可以使用二分查找
        //p1指向前面的排序數組,p2指向後面的排序數組
        //如果數組本身就有序(旋轉0個元素),直接返回mid的值
        int mid = p1;
        while(p1 < p2 && array[p1] >= array[p2]) {
            if(p2 - p1 == 1) {
                mid = p2;
                break;
            }
            
            mid = p1 + (p2 - p1) / 2;
            //特殊情況:p1, mid, p2三者相等
            if(array[p1] == array[mid] && array[p2] == array[mid]) {
                //順序查找
                int res = array[p1];
                for(int i=p1+1; i<=p2; i++) {
                    res = Math.min(res, array[i]);
                }
                return res;
            }
            //判斷當前mid是否位於前面的排序數組中
            if(array[mid] >= array[p1]){
                p1 = mid;
            } else if(array[mid] <= array[p2]) {
                p2 = mid;
            }
        }
        
        return array[mid];
    }
 }

解法一爲直接遍歷數組找最小值,雖然複雜度爲O(n),但並沒有利用題目中所說的排序數組的條件(雖然是旋轉的排序數組).想到排序數組的查找應該就是二分查找了,這道題是變種的二分查找。

具體解法爲:

1)兩個指針p1, p2分別指向數組的起始和結束位置(和普通的二分查找一樣)

2)中間元素:這裏需要考慮如何根據和中間元素的比較來縮小查找的範圍,普通的二分查找直接比較就好了。觀察這裏的數組,排序數組被分爲了兩部分:前半部分(旋轉的)和後半部分,若中間元素mid大於等於p1,則mid一定在前半部分的排序數組,這時可以將p1移到mid的位置:p1=mid。同理,若mid小於等於p2,則p2=mid。最後p1指向的是前半部分的最後一個元素,p2指向的是後半部分的第一個元素(即最小元素)

例子:3 4 5 1 2

需要注意的特殊情況:

1)數組可能旋轉了0個元素(即沒有旋轉)

2)p1、mid、p2三者指向的元素相等,即無法判斷中間的數字是位於前面的子數組還是後面的子數組,從而無法移動指針縮小查找範圍。這時不得不採用順序查找的方法。

例子:1 0 1 1 1 和1 1 1 0 1

(加陰影的爲旋轉的)

參考劍指offer題解

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