題目:把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。輸入一個遞增排序的數組的一個旋轉,輸出旋轉數組的最小元素。例如:{3,4,5,1,2},{4,5,1,2,3}都是數組{1,2,3,4,5}的旋轉,該數組的最小值爲1。有相同數字的情況,如{1,0,1,1,1},{1,1,1,0,1}都可以看做是數組{0,1,1,1,1}的旋轉。
/*
* 旋轉數組中的最小數字
* 算法思想:二分查找的變型,設置兩個指針low,high分別指向數組的開頭與結尾。如果中間位置的數字大於low指向的數字,則low = mid;如果中間位置的數字小於high指向的數字,則high = mid;
* 特殊情況:low high 以及中間的元素的值均相等,這時無法利用上述方法進行判斷,對數組按照順序查找即可。
* */
public class RotateMin {
public static int minNumberInRotateArray(int[] arr){
int low = 0; //從前往後走
int high = arr.length - 1; //從後往前走
int mid = 0;
int min = arr[low]; //如果沒有發生旋轉,直接返回arr[0]
while(arr[low] >= arr[high]){
if(high - low == 1){ //當兩個指針走到挨着的位置的時候,p2就是最小值
min = arr[high];
break;
}
mid = (low + high) >> 1;
//如果中間元素的值,與首尾指針指向的數字相同,則進行順序查找即可
if(arr[low] == arr[mid] && arr[mid] == arr[high]){
min = minOrder(arr, low, high);
}
if(arr[low] <= arr[mid]){ //如果中間位置的數字位於數組1,讓low走到mid的位置
low = mid;
}else if (arr[high] >= arr[mid]) { //若中間位置的數字位於數組2中,讓high走到mid的位置
high = mid;
}
}
return min;
}
public static int minOrder(int[] arr, int low,int high){
int min = arr[low];
for(int i = low + 1; i <= high; i++){
if(arr[i] < min){
min = arr[i];
}
}
return min;
}
public static void main(String[] args) {
int[] arr = {4,5,1,2,3};
int[] arr1 = {1,1,1,0,1};
System.out.println("旋轉數組中最小的數字是:" + minNumberInRotateArray(arr));
System.out.println("有相同數字的旋轉數組中的最小數字是:" + minNumberInRotateArray(arr1));
}
}