旋轉數組的最小數字

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

發現用二分法解決這個問題很好,{3,4,5,1,2}能夠分紅兩個排好序的子數組{3,4,5}{1,2},而左邊的每一個數必定大於右邊的每一個數,因此能夠聲明兩個索引left=0,right=length-1,mid=left(爲啥這麼設置初始值請看代碼註釋).
開始循環,循環條件爲list[left] >= list[right]。咱們要作的事情就是讓left一直處於第一個數組裏且不斷接近第一個數組尾,讓right一直處於數組二且不斷接近數組二的頭。讓mid等於(left+right)/2,當mid大於left時,說明此時mid還在第一個數組裏,這時就讓left=mid;繼續循環mid再等於(left+right)/2,假設此時mid小於left了,那麼它必定處於第二個數組裏了,並且它也小於right(由於right時第二個數組當前最大的).當left+1==right的時候就能夠跳出循環了,由於此時right就是咱們要找的元素。數組

public class Jianzhi{

    public static void main (String[] args){
        int[] num = {3,4,5,1,2};
        int m = find(num ) ;
        System.out.println(m);
    }
    public static int find(int[] list) {
        if(list == null){  //數組爲null時
            return -1 ;
        }
        if(list.length == 0 ){  //數組長度爲0則返回0
            return 0 ;
        }
        int left = 0 ;    
        int right = list.length - 1 ;
        int mid = left ;    //注意:這一步讓mid等於left是有用意的,若是list是排好序的,
                            //那麼直接返回list[mid] 
        while(list[left] >= list[right]){ 
            if(left + 1 == right){
                    return right ;
            }
            mid = (left + right) / 2 ;
            if(list[mid] == list[left] && list[mid] == list[right]){
                return minInOrder(list,left,right);
            }
            if(list[mid] >= list[left]){
                left = mid ;
            }
            if(list[mid] <= list[right] ){
                right = mid  ;
            }
        }
        return list[mid] ;
    }
public static int minInOrder(int[] list , int left , int right ){
    int result = list[left] ;
    for(int i = left+1 ; i < right ; i++){
        if(result > list[i] ){
            result = list[i] ;
        }
    }
    return result ;
}

}

可能你們比較疑惑爲何有如下這句:spa

if(list[mid] == list[left] && list[mid] == list[right]){
                return minInOrder(list,left,right);
            }

考慮下面這種狀況
圖片描述code

此時 第一個和第二個索引以及mid索引指向的指都是1,三個數字相同。但咱們不能區分出最小的數字在mid的左邊仍是右邊,就無法進行判斷了。此時,就不得不採用順序查找方法:排序

public static int minInOrder(int[] list , int left , int right ){
        int result = list[left] ;
        for(int i = left+1 ; i < right ; i++){
            if(result > list[i] ){
                result = list[i] ;
            }
        }
        return result ;
    }

整個算法最重要的仍是讓left和right都往兩個數組的公共邊界靠攏。索引

完畢。圖片

相關文章
相關標籤/搜索