1. 程式人生 > >劍指Offer-題11(Java版):旋轉陣列的最小數字

劍指Offer-題11(Java版):旋轉陣列的最小數字

參考自:《劍指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; } }