旋转数组的最小数字-剑指Offer(Java语言)

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{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  且左边序列的每一个元素都大于右边序列的所有元素。要求的最小值为两个序列的交界,即右边序列的第一个值。

使用二分查找

分为三种情况:

  1. 若array[mid]>array[high],则array[mid]位于左边的序列. low=mid+1
  2. 若array[mid]<array[high],则array[mid]与array[high]位于同一序列,则最小值是array[mid]或者在mid的左边。high=mid
  3. 若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

猜你喜欢

转载自blog.csdn.net/ChaunceyChen/article/details/87899887