7.把一個數組最開始的若干元素搬到數組的末尾,我們稱之爲數組的旋轉。
輸入一個遞增排序數組的一個旋轉,輸出旋轉數組的最小元素。例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1.
題目信息:1.數組旋轉,有2個排好序的子數組
2.前面子數組元素大於等於後面子數組元素
3.最小元素是兩個子數組分界線
利用二分查找來實現O(logn)時間複雜度
(1)指針1指向第一個位置數字,指針2指向最後位置的數字。
(2)中間位置數字如果比指針1所指數字大,說明中間位置屬於前面的子數組,最小值在中間位置之後;如果中間位置數字比指針2所指數字大,說明中間位置屬於後面的子數組,最小值在中間位置之前。
(3)當兩指針距離爲1時,表明指針1已經在前面子數組的末尾,指針2在後面子數組的開頭,最小值就是後面子數組的第一個數字。
(4)如果兩個指針指向的數字以及中間位置數字相等時,就無法判斷屬於哪一個子數組,也就無法移動指針來縮小範圍。此時就需要採用順序查找的方法。
public class javatest {
/**
* @param numbers 旋轉數組
* @return 數組的最小值
*/
public static int min(int[] numbers) {
// 判斷輸入是否合法
if (numbers == null || numbers.length == 0) {
throw new RuntimeException("Invalid input.");
}
// 開始處理的第一個位置
int lo = 0;
// 開始處理的最後一個位置
int hi = numbers.length - 1;
// 設置初始值
int mi = lo;
// 確保lo在前一個排好序的部分,hi在排好序的後一個部分
while (numbers[lo] >= numbers[hi]) {
// 當處理範圍只有兩個數據時,返回後一個結果
// 因爲numbers[lo] >= numbers[hi]總是成立,後一個結果對應的是最小的值
if (hi - lo == 1) {
return numbers[hi];
}
// 取中間的位置
mi = lo + (hi - lo) / 2;
// 如果三個數都相等,則需要進行順序處理,從頭到尾找最小的值
if (numbers[mi] == numbers[lo] && numbers[hi] == numbers[mi]) {
return minInorder(numbers, lo, hi);
}
// 如果中間位置對應的值在前一個排好序的部分,將lo設置爲新的處理位置
if (numbers[mi] >= numbers[lo]) {
lo = mi;
}
// 如果中間位置對應的值在後一個排好序的部分,將hi設置爲新的處理位置
else if (numbers[mi] <= numbers[hi]) {
hi = mi;
}
}
// 返回最終的處理結果
return numbers[mi];
}
/**
* 找數組中的最小值
*
* @param numbers 數組
* @param start 數組的起始位置
* @param end 數組的結束位置
* @return 找到的最小的數
*/
public static int minInorder(int[] numbers, int start, int end) {
int result = numbers[start];
for (int i = start + 1; i <= end; i++) {
if (result > numbers[i]) {
result = numbers[i];
}
}
return result;
}
public static void main(String[] args) {
// 典型輸入,單調升序的數組的一個旋轉
int[] array1 = {3, 4, 5, 1, 2};
System.out.println(min(array1));
// 有重複數字,並且重複的數字剛好的最小的數字
int[] array2 = {3, 4, 5, 1, 1, 2};
System.out.println(min(array2));
// 有重複數字,但重複的數字不是第一個數字和最後一個數字
int[] array3 = {3, 4, 5, 1, 2, 2};
System.out.println(min(array3));
// 有重複的數字,並且重複的數字剛好是第一個數字和最後一個數字
int[] array4 = {1, 0, 1, 1, 1};
System.out.println(min(array4));
// 單調升序數組,旋轉0個元素,也就是單調升序數組本身
int[] array5 = {1, 2, 3, 4, 5};
System.out.println(min(array5));
// 數組中只有一個數字
int[] array6 = {2};
System.out.println(min(array6));
// 數組中數字都相同
int[] array7 = {1, 1, 1, 1, 1, 1, 1};
System.out.println(min(array7));
// 輸入NULL
System.out.println(min(null));
}
}
輸出結果:1
1
1
0
1
2
1