題目:把一個數組最開始的若干個元素搬到數組的末尾, 我們稱之數組的旋轉。輸入一個遞增排序的數組的一個旋轉, 輸出旋轉數組的最小元素。例如數組{3,4,5,1,2 }為{1,2,3,4,5}的一個旋轉,該數組的最小值為1。
最直接的解法:從頭到尾遍歷數組查找。時間復雜度O(n)。但是這種思路沒有利用旋轉數組的特性。
public int minArray(int[] numbers) {
if (numbers == null) {
//注意:我們假設`-5000 <= numbers[i] <= 5000`,
return -5001;
}
if (numbers.length == 1) {
return numbers[0];
}
int lastIndex = numbers.length;
int index = 0;
for (int i = 0; i < lastIndex - 1; i++) {
if (numbers[i] > numbers[i + 1]) {
index = i + 1;
break;
}
}
return numbers[index];
}
第二種解法
旋轉后的數組實際上可以劃分為兩個排序的子數組,而且前面子數組的元素都大于或者等于后面子數組的元素。我們還注意到最小元素剛好是這兩個子數組的分界線。在排序的數組中我們可以用二分查找法實現O(logn)的查找。本題給出的數組在一定程度上是排序的,因此可以試著用二分查找的思路來尋找最小元素。
private static int min(int[] numbers) {
if (numbers == null || numbers.length == 0) {
throw new IllegalArgumentException("Invalid input.");
}
int low = 0;
int high = numbers.length - 1;
//設置初始值
int mid = low;
while (numbers[low] >= numbers[high]) {
if (high - low == 1) {
mid = high;
break;
}
mid = (low + high) / 2;
//注釋1處,如果三個數都相等,則需要進行順序查找
if (numbers[mid] == numbers[low] && numbers[mid] == numbers[high]) {
return minInOrder(numbers, low, high);
}
if (numbers[mid] >= numbers[low]) {
low = mid;
} else if (numbers[mid] <= numbers[high]) {
high = mid;
}
}
return numbers[mid];
}
/**
* 順序查找
*
* @param numbers
* @param low
* @param high
* @return
*/
private static int minInOrder(int[] numbers, int low, int high) {
int result = numbers[low];
for (int i = low + 1; i <= high; i++) {
if (result > numbers[i]) {
result = numbers[i];
}
}
return result;
}
注釋1處,如果三個數都相等,則需要進行順序查找,這三個數不是連著的,可能是如下:
int[] array = {3,3,1,3};
第一次進來,low = 0 ,high =3 ,mid = 1
array[0] = array[1] = array[3] ,這個時候就要順序查找。
測試用例
public static void main(String[] args) {
// 旋轉0個元素
int[] array0 = {1, 2, 3, 4, 5};
System.out.println(min(array0));
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));
// 數組中只有一個數字
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));
}
參考鏈接: