题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
思路
由题意可知,如果发生了旋转,即若干个元素搬到末尾,若干不为0,则数组内部分成了两个非减的序列,对于例子{3,4,5,1,2},左边一个序列,如3,4,5 右边一个序列如1,2 且左边序列的每一个元素都大于右边序列的所有元素。要求的最小值为两个序列的交界,即右边序列的第一个值。
使用二分查找
分为三种情况:
- 若array[mid]>array[high],则array[mid]位于左边的序列. low=mid+1
- 若array[mid]<array[high],则array[mid]与array[high]位于同一序列,则最小值是array[mid]或者在mid的左边。high=mid
- 若array[mid]=array[high],不清楚最小值在mid的左边还是右边。如序列{2,1,2,2,2}在mid的左边,序列{2,2,2,1,2}在mid的右边。故只能一个一个试,high=high-1。这里不用low=low+1是因为存在搬0个元素的情况。如序列{1,2,3,4,5},用low=low+1则错过了最小值。
代码
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
if(array.length==0) return 0;
int low=0,high=array.length-1;
while(low<high){
int mid=low+(high-low)/2;//这样算mid是为了防止high+low溢出
if(array[mid]>array[high]){
low=mid+1;
}else if(array[mid]<array[high]){
high=mid;
}else{
high--;
}
}
return array[low];
}
}
其他
也可以将array[mid]与array[low]比较,但是注意当相等时,不能用low=low+1,而是用high=high-1