旋轉數組的最小數字
參見《劍指Offer》P66
題目描述:
把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。 輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。 NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。
思路:
根據題意,將一個數組旋轉之後,變成了兩個獨立的非降序的數組,且前一個數組的元素應該大於後一個數組的元素。我們要找的最小的數字就位於兩個數組交叉處,也就是第二個數組的首元素。
利用二分查找思想,查找範圍爲數組的[left,right],開始left=0,right=length-1,中間位置mid=(left+right)/2。
如果中間元素大於left位置的元素,說明中間元素位於前一個遞增數組中,此時可以將left移動到mid;
如果中間元素小於right位置的元素,說明中間元素位於後一個遞增數組中,此時可以將right移動到mid;
如此循環下去,直到right-left=1,此時right就是我們要找的元素。
特殊情況:如10111和11101都是01111的旋轉,此時left==mid==right,此時無法判斷中間元素是位於前邊的遞增數組還是位於後邊的遞增數組,只能在left到right之間順序查找。
代碼如下:
#include<iostream>
#include<vector>
#include<algorithm>
#include<limits.h>
using namespace std;
//順序搜索
int orderedSearch(vector<int> rotateArray,int lo,int hi) {
int result = INT_MAX;
for(int i=lo;i<=hi;i++) {
result = rotateArray[i]<result? rotateArray[i]:result;
}
return result;
}
int minNumberInRotateArray(vector<int> rotateArray) {
if(rotateArray.size()==0) return 0;
if(rotateArray.size()==1) return rotateArray[0];
int left = 0,right = rotateArray.size()-1;
int mid = left; //數組原來有序,直接返回
while(rotateArray[left]>=rotateArray[right]) {
if(right-left == 1) {
mid = right;
break;
}
mid = (left+right)/2;
if(rotateArray[mid]>=rotateArray[left])
left = mid;
else if(rotateArray[mid]<=rotateArray[right])
right = mid;
else if(rotateArray[mid] == rotateArray[left] == rotateArray[right])
return orderedSearch(rotateArray, left, right);
}
return rotateArray[right];
}
int main()
{
vector<int> a = {1,1,1,0,1};
cout<<minNumberInRotateArray(a)<<endl;
return 0;
}