題目:
把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。 輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。 NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。
分析&解法:
解法1:
首先可以使用遍歷的方法找出其中最小數字,但是由於該時間複雜度爲O(n),不是最優解法。
解法2:
雖然是旋轉數組,但是基本還是有一定的排序規律的,通過觀察可以發現經過旋轉後遞增區域劃分成了兩半如圖:
3 | 4 | 5 | 1 | 2 | |
左邊較大值大遞增區域 | 右邊較小值遞增區域 |
故通過這一特點我們可以考慮使用二分查找的方法:
初始化 (陰影區域爲最小值所在區域):
3 | 4 | 5 | 1 | 2 |
startIndex | midIndex | endIndex |
通過分別和startIndex、endIndex比較大小後,可分爲三種情況:
比startIndex大:
則最小值在midIndex-endStart之間
比endIndex小:
則最小值在startIndex-midIndex之間
三者相等:
舉例:{1,0,1,1,1} 和{1,1,1,0,1}都可以視爲 {0,1,1,1,1}的旋轉
但是他們三者相等,最小值卻分別在左邊和右邊,故無法判斷,轉爲使用遍歷方法。
以剛纔的例子進行第一次劃分:
3 | 4 | 5 | 1 | 2 |
startIndex | midIndex | endIndex |
第二次劃分:
3 | 4 | 5 | 1 | 2 |
startIndex | endIndex |
則當兩個index相鄰的時候可以的代minIndex
代碼如下:
package problem8;
/**
* Created by fengyuwusong on 2018/1/29 15:09.
* 題目描述
* 把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。
* 輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。
* 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。
* NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。
* 陷阱:
* 1. 把一個數組最開始的若干個元素搬到數組的末尾 若干個包括0 級排序數組本身
* 2. {1,0,1,1,1} 和{1,1,1,0,1}都可以視爲 {0,1,1,1,1}的旋轉
*/
public class Main {
// 解法1:遍歷 時間複雜度O(n) 不考慮
// 解法2:二分查找 時間複雜度 O(logn)
public int minNumberInRotateArray(int[] array) {
if (array.length==0){
return 0;
}
int startIndex,endIndex,midIndex;
startIndex=0;
endIndex=array.length-1;
// 預防陷阱1
midIndex=array[startIndex];
while (array[startIndex]>=array[endIndex]){
// 跳出循環條件 如果start和end索引相鄰
if (endIndex-startIndex==1){
midIndex=endIndex;
break;
}
// 找出中間 並移動座標
midIndex=(startIndex+endIndex)/2;
// 預防陷阱2 如果start end mid值相等 則只能按照順序查找
if (array[startIndex]==array[endIndex]&&array[startIndex]==array[midIndex]){
return MinInOrder(array,startIndex,endIndex);
}
if (array[midIndex]>=array[startIndex]){
startIndex=midIndex;
}else if (array[midIndex]<=array[endIndex]){
endIndex=midIndex;
}
}
return array[midIndex];
}
private int MinInOrder(int[] array, int startIndex, int endIndex) {
int min=array[startIndex];
for (int i = startIndex; i <=endIndex; i++) {
// 優化遍歷 觀察可發現一旦後面小於前面第一個則該值最小
if (array[startIndex]>=array[i]){
min=array[i];
}
}
return min;
}
public static void main(String[] args) {
Main main=new Main();
int min=main.minNumberInRotateArray(new int[]{3,4,5,1,2});
System.out.println(min);
}
}