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

題目

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

解題思路

這是一道二分查找的變形題,這裏的旋轉數組是兩個有序的遞增子數組拼接起來的,且前面一個子數組裏的任意一個數都大於後面子數組中的數。而要找的最小值就是先後兩個子數組的分界點。spa

 

用三個指針begin、end、middle分別指向數組的首尾和中間元素指針

1)若middle元素大於或者等於begin元素說明中間元素位於前半部分數組中,最小元素在後半部分的數組中,則將begin設爲middle繼續在後半部分中尋找code

2)若middle元素小於或者等於end元素說明中間元素位於後半部分數組中,最小部分在前半部分或者中間元素就是最小元素,則將end設爲middle繼續在前半部分中尋找blog

這樣不斷縮小範圍,直到最後begin和end會成爲相鄰的元素,此時end所指元素就是最小值排序

 

特殊狀況:class

1)0個元素旋轉到後半部分,那麼此時旋轉數組就是一個非遞減數組,最小值就是第一個元素,也就是爲何初始middle設爲0的緣由遍歷

2)當begin、end、middle三個元素都相等時,沒法判斷中間元素在前半部分數組仍是後半部分數組,只能遍歷數組尋找最小值di

例如1,1,1,0,1和1,0,1,1,1均可以當作是0,1,1,1,1的翻轉數組while

 

代碼

 1     public int minNumberInRotateArray(int [] array) {
 2         if(array.length==0)
 3             return 0;
 4         int begin = 0,end = array.length-1,middle = 0;
 5         while(array[begin]>=array[end]){
 6             if((end-begin)==1){
 7                 middle = end;
 8                 break;
 9             }
10             middle = (begin+end)/2;
11             if(array[begin]==array[middle]&&array[middle]==array[end]){
12                 return minInOrder(array,begin,end);
13             }
14             if(array[middle]>=array[begin]){
15                 begin = middle;
16             }else if(array[middle]<=array[end]){
17                 end = middle;
18             }
19             
20         }
21         return array[middle];
22     }
23     
24     private int minInOrder(int[] array,int begin,int end){
25         int min = array[begin];
26         for(int i = begin+1;i<end;i++){
27             if(min>array[i]){
28                 min = array[i];
29             }
30         }
31         return min;
32     }
相關文章
相關標籤/搜索