劍指Offer-題11(Java版):旋轉陣列的最小數字
阿新 • • 發佈:2019-01-03
參考自:《劍指Offer——名企面試官精講典型程式設計題》
題目:旋轉陣列的最小數字
把一個數組最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入一個遞增排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。例如陣列 {3, 4, 5, 1, 2}為{1, 2, 3, 4, 5}的一個旋轉,該陣列的最小值為1。
主要思路:旋轉後的陣列分成兩個排序的子陣列,前面的子陣列都大於或等於後面的子陣列,最小元素就是兩個子陣列的分界線。因此,使用兩個指標(左指標和右指標)分別指向第一個元素和最後一個元素,接著找到陣列的中間元素((左指標+右指標)/2),判斷其與兩個指標指向元素的大小。
分三種情況:
1.若中間元素大於或等於左指標
2.若中間元素小於或等於右指標指向的元素:說明中間元素位於後面的非遞減子陣列,最小元素應該位於該中間元素的前面,因此把右指標指向中間元素,縮小查詢範圍。
1和2情況中要移動指標,直到左指標指向前面子陣列的最後一個元素,右指標指向後面子陣列的第一個元素(該元素即為最小值)。
3.若中間元素同時等於左指標和右指標指向的元素,則只能按順序查詢。
關鍵點:陣列部分有序,縮小查詢範圍,二分查詢
時間複雜度:O(logn)
public class MinNumberInRotateArray
{
public static void main(String[] args)
{
int[] array1 = {3, 4, 5, 1, 2};
int[] array4 = {1, 0, 1, 1, 1};
System.out.println(findMinNumberInArray(array1));
System.out.println(findMinNumberInArray(array4));
}
private static int findMinNumberInArray(int[] array)
{
if (array == null || array.length <= 0) return -1;
int leftIndex = 0; //左指標
int rightIndex = array.length - 1;
int midIndex = leftIndex;
while (array[leftIndex] >= array[rightIndex])
{
//左右指標相鄰,找到最小值
if (rightIndex - leftIndex == 1)
{
midIndex = rightIndex;
break;
}
midIndex = (leftIndex + rightIndex) / 2;
//前中後三個值相等,則順序查詢
if ((array[leftIndex] == array[rightIndex])
&& (array[leftIndex] == array[midIndex]))
{
return minInOrder(array, leftIndex, rightIndex);
}
//中間值大於或等於左指標指向元素(前半段還是非遞減),則最小值在後半段
if (array[midIndex] >= array[leftIndex])
{
leftIndex = midIndex;
}
//中間值小於或等於右指標指向元素(後半段還是非遞減),則最小值在前半段
else if (array[midIndex] <= array[rightIndex])
{
rightIndex = midIndex;
}
}
return array[midIndex];
}
//順序查詢最小值
private static int minInOrder(int[] array, int aheadIndex, int behindIndex)
{
int result = array[aheadIndex];
for (int i = aheadIndex + 1; i <= behindIndex; i++)
{
if (result > array[i])
{
result = array[i];
}
}
return result;
}
}