[剑指offer][Java]旋转数组的最小数字

2019-06-20  本文已影响0人  Maxinxx

题目

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

程序核心思想

看到题目是一个非减的排序了的数组,并且只经过一次旋转,所以对于这种基本已经有序的数组,可以采用二分法,找到其中最小的那个数。
比如3,4,5,1,2是一个旋转,用二分查找来做,如果mid指向的数比max指向的数要大,说明进行了旋转的部分一定在mid右边,所以让min=mid+1;如果mid指向的数比max指向的数要小,说明进行了旋转的部分一定在mid的左边,所以让max=mid,这个地方我查了好久的错,我写的是max=mid-1,原因是如果mid碰巧是要找的(旋转点),它满足比max小,所以如果直接让max=mid-1,就会错过旋转点,这是因为题目让找的是最小值;如果让找最大值呢?mid如果比max小,则max=mid-1;如果mid比max大,那么min=mid。具体问题具体分析。

Tips

因为经过指针的移动,会出现max<min的情况,这个时候就不好判断正确答案了。我的方法是,经过分析,只允许出现两种情况,第一种min=max,结果输出min和max是一样的;第二种:max如果比min小的话,只会比min小1,所以如果检测到max<min,那么令max++或min--(看是max主动减小的,还是min主动增大的),使得min=max,最终输出结果。如果max>min,就要继续二分,直到max=min或max<min(按上述办法处理,使其最后相等)。

代码

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        if(array.length == 0)    return 0;
        if(array[0] < array[array.length-1])    return array[0];
       
        int min = 0;
        int max = array.length-1;
        int mid = (min+max)/2;
        
        while(max > min){
            if(array[mid] > array[max]){
                min = mid + 1;
                if(min > max){
                    min--;
                    break;
                }
                mid = (min+max)/2;
            }else{
                max = mid;
                if(max < min){
                    max++;
                    break;
                }
                mid = (min+max)/2;
            }
        }

        return array[max];
    }
}
上一篇 下一篇

猜你喜欢

热点阅读