題目:把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉,輸入一個遞增排序的數組的一個旋轉,輸出旋轉數組的最小元素。例如數組{3,4,5,1,2}是數組{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。
題目分析:
我們可以通過旋轉以後的數組中的元素的分佈方式找出其中的一些規律:
數組{3,4,5,1,2}中,最左邊的數字(3)大於最右邊的數字(2),由於原數組是遞增排序的,所以左邊的數字(3,4,5)都比右邊的數字(1,2)大,這樣我們可以將該數組劃分爲兩個序列分別是序列1{3,4,5}、序列2{1,2},那麼我們就可以按照二分查找的方法查找最小數字1。
具體查找方法如下:
如:該數組爲
int arr[5]={3,4,5,1,2};
第一步:用兩個指針分別指向該數組的第一個元素和最後一個元素,即arr[0]arr[4];
第二步:查找數組的中間元素arr[mid];
第三步:用中間元素和數組的第一個元素分別和第一個元素和最後一個元素作比較,如果中間元素比第一個元素大,那麼該中間元素一定是在第一個序列中的,這時,將第一個指針指向中間元素即arr[2];如果中間元素小與最後一個元素,那麼中間元素一定是在第二個序列中的,這時將第二個指針指向中間元素。
第四步:重複上述步驟二,直到第一個指針指向第一個序列的最後一個元素,第二個指針指向第二個序列的第一個元素,即兩個指針相鄰,那麼最小的元素就是第二個指針所指向的元素。
如圖:
通過分析題目我們就可以很好的寫出程序了,當然我們也要考慮到其他情況,當數組中元素爲
{1,1,1,0,1}或{1,0,1,1,1}時,我們無法判斷中間元素在第幾個序列中,這是我們就要用另一種方法進行查找最小元素了。
代碼如下:
#include<stdio.h> #include<stdlib.h> #include<assert.h> int Min(int *arr,int size) { assert(arr); assert(size >=0); int left = 0; int right = size - 1; int mid = left; while (arr[left] >= arr[right]) { if (right - left == 1)//若兩指針相鄰,則後一個指針所指的元素爲最小值 { mid = right; break; } mid = (left + right) / 2;//求中間元素 if ((arr[left] == arr[right]) && (arr[mid] == arr[left])) //若出現中間元素和左右兩邊的元素都相等時直接找最小元素,用下面的函數實現 return MinInOrder(arr,left,right); if (arr[mid] >= arr[left]) { left = mid; } else if (arr[mid] <= arr[right]) { right = mid; } } return arr[mid]; } int MinInOrder(int *arr, int left, int right) { int i = 0; int min = arr[left]; for (i = left + 1; i < right; i++)//直接遍歷數組尋找最小的元素 { if (arr[left]>arr[i]) { min = arr[i]; break; } } return min; }