题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
使用二分查找,在arr[left..right]上找到这个范围的最小值
1.若果arr[left] < arr[right] 那么arr[left]就是最小值,直接返回即可。
2.令mid = (left + right)/2,mid即数组的中间位置
1)如果 arr[left] > arr[mid],说明要找的数在mid的左边,令 right = mid,然后回到步骤一。
2)如果 arr[right] < arr[mid],说明要找的数在mid的右边,令 left = mid,然后回到步骤一。
3.1和2没有命中的情况就是 arr[left] >= arr[right],arr[left] <= arr[mid],arr[right] >= arr[mid],所以剩余的情况为 arr[left] = arr[mid] = arr[right]
此时可以直接遍历找到最小值,我依然使用二分查找,从i开始向右遍历,设i = left。
情况1:arr[i] < arr[mid] 说明arr[i]就是最小值,直接返回。
情况2:arr[left] < arr[i]说明arr[i] > arr[mid] ,令right = mid,然后回到步骤一。
情况3:如果到i == mid都没有出现上面2种情况,说明从left到mid的值全部一样,令left = mid,然后回到步骤一
public int minNumberInRotateArray(int [] array) {
int left = 0;
int right = array.length - 1;
int mid = 0;
while(left < right){
if(array.length == 0) return 0;
if(left == right - 1) break;
if(array[left] < array[right])
return array[left];
mid =(left + right)/2;
if(array[left] > array[mid]){
right = mid;
continue;
}
if (array[right] < array[mid]){
left = mid;
continue;
}
while(left < mid){
if(array[left] == array[mid])
left++;
else if(array[left] < array[mid])
return array[left];
else {
right = mid;
break;
}
}
}
return Math.min(array[left],array[right]);
}