旋轉數組中的最小元素

題目:把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。輸入一個排好序的數組的一個旋轉,輸出旋轉數組的最小元素。例如數組{3, 4, 5, 1, 2}爲{1, 2, 3, 4, 5}的一個旋轉,該數組的最小值爲1。

分析:這道題最直觀的解法並不難。從頭到尾遍歷數組一次,就能找出最小的元素,時間複雜度顯然是O(N)。但這個思路沒有利用輸入數組的特性,我們應該能找到更好的解法。
我們注意到旋轉之後的數組實際上可以劃分爲兩個排序的子數組,而且前面的子數組的元素都大於或者等於後面子數組的元素。我們還可以注意到最小的元素剛好是這兩個子數組的分界線。我們試着用二元查找法的思路在尋找這個最小的元素。
首先我們用兩個指針,分別指向數組的第一個元素和最後一個元素。按照題目旋轉的規則,第一個元素應該是大於或者等於最後一個元素的(當然這裏有特列,就是旋轉個數爲0即沒有旋轉的時候,我們要單獨處理)。
接着我們得到處在數組中間的元素。如果該中間元素位於前面的遞增子數組,那麼它應該大於或者等於第一個指針指向的元素。此時數組中最小的元素應該位於該中間元素的後面。我們可以把第一指針指向該中間元素,這樣可以縮小尋找的範圍。同樣,如果中間元素位於後面的遞增子數組,那麼它應該小於或者等於第二個指針指向的元素。此時該數組中最小的元素應該位於該中間元素的前面。我們可以把第二個指針指向該中間元素,這樣同樣可以縮小尋找的範圍。我們接着再用更新之後的兩個指針,去得到和比較新的中間元素,循環下去。按照上述的思路,我們的第一個指針總是指向前面遞增數組的元素,而第二個指針總是指向後面遞增數組的元素。最後第一個指針將指向前面子數組的最後一個元素,而第二個指針會指向後面子數組的第一個元素。也就是它們最終會指向兩個相鄰的元素,而第二個指針指向的剛好是最小的元素。這就是循環結束的條件。

#include <iostream>
using namespace std;

int FindMin(int *a, int length)
{
	int low=0;
	int high=length-1;
    int mid;

	if(a[low]<a[high])//如果旋轉個數爲0,即沒有旋轉,單獨處理,直接返回數組頭元素
		return a[low];

	while(low<=high)
	{
		mid=(low+high)/2;
		if(a[low]<a[mid])
			low=mid;
		else if(a[low]>a[mid])
			high=mid;
		else if(a[low]==a[mid])
			return a[low+1];
	}	
}

int main()
{
	int a[]={3,4,5,6,7,1,2};
	cout<<FindMin(a, 7)<<endl;

}


 

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