把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
分析:
可以采用二分法来解决这个问题:
如果arr[m] >= arr[high],那么就证明最小的数在后个序列中,所以low = mid;
如果arr[m] < arr[low],那么就证明最小的数在前半个序列中,所以high = mid。
特殊情况:
当arr[mid] == arr[low] == arr[high]的时候,无法确定最小值在哪个区间。此时,需要切换到顺序查找,每个数之间俩俩比较,如果存在前一个数大于后一个数,则返回后一个较小的数;否则,就证明是前一个数比较大,返回前一个数。
package swordOffer;
public class minNumberInRotateArray {
public static int minNumberInRotateArray(int [] array) {
int low = 0;
int high = array.length - 1;
while(low < high) {
int mid = low + (high - low)/2;
if(array[low] == array[mid] && array[mid] == array[high]) {
return minNumber(array, low, high);
}else if(array[mid] <= array[high]) {
high = mid;
}else {
low = mid + 1;
}
}
return array[low];
}
private static int minNumber(int[] array, int low, int high) {
for(int i = low; i < high; i++) {
if(array[i] > array[i+1]) {
return array[i+1];
}
}
return array[low];
}
public static void main(String[] args) {
int[] array1 = {3,4,5,1,2};
int min1 = minNumberInRotateArray(array1);
System.out.println(min1);
System.out.println("--------------------------");
int[] array2 = {1,0,1,1,1};
int min2 = minNumberInRotateArray(array2);
System.out.println(min2);
}
}