把一個數組最開始的若干個元素搬到數組的末尾,我們稱之為數組的旋轉。輸入一個排好序的數組的一個旋轉,輸出旋轉數組的最小元素。例如數組{3, 4, 5, 1, 2}為{1, 2, 3, 4, 5}的一個旋轉,該數組的最小值為1。
這道題最直觀的解法並不難。從頭到尾遍歷數組一次,就能找出最小的元素,時間復雜度顯然是O(N)。但這個思路沒有利用輸入數組的特性,我們應該能找到更好的解法。
我們注意到旋轉之後的數組實際上可以劃分為兩個排序的子數組,而且前面的子數組的元素都大於或者等於後面子數組的元素。我們還可以注意到最小的元素剛好是這兩個子數組的分界線。我們試著用二元查找法的思路在尋找這個最小的元素。
我們得到處在數組中間的元素。如果該中間元素位於前面的遞增子數組,那麼它應該大於或者等於第一個指針指向的元素。此時數組中最小的元素應該位於該中間元素的後面。我們可以把第一指針指向該中間元素,這樣可以縮小尋找的范圍。同樣,如果中間元素位於後面的遞增子數組,那麼它應該小於或者等於第二個指針指向的元素。此時該數組中最小的元素應該位於該中間元素的前面。我們可以把第二個指針指向該中間元素,這樣同樣可以縮小尋找的范圍。我們接著再用更新之後的兩個指針,去得到和比較新的中間元素,循環下去。
/********************************* * 日期:2015-01-04 * 作者:SJF0115 * 題目: 輸入一個排好序的數組的一個旋轉,輸出旋轉數組的最小元素 * 博客: **********************************/ #includeusing namespace std; int SearchMin(int A[],int n){ if(n <= 0){ return -1; }//if int start = 0,end = n-1; // 數組有序 if(A[end] > A[start]){ return A[start]; }//if // 數組旋轉 // 二分查找 while(start <= end){ int mid = (start + end) / 2; // [start,mid]有序[mid,end]無序 if(A[mid] > A[start]){ start = mid; } // [start,mid]無序[mid,end]有序 else if(A[mid] < A[start]){ end = mid; } else{ return A[mid+1]; } }//while } int main(){ int A[] = {2,3,4,5,6,7,8}; cout<