剑指Offer系列——旋转数组的最小数字

地址

https://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba?tpId=13&tqId=11159&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目

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

思路

1.旋转数组可以看做两个非减排序数组,第一个数组中的元素必定大于或等于第二个数组中的元素
2.题目中的元素最小值为这两个数组的分界点。所以这里设定两个指针,一个指向数组首位(low),另一个指向数组末尾(high),使用二分查找缩小查找范围,当high-low == 1时,表示已经到达两个数组的分界点,因此这个作为循环的停止条件。
3.当首元素等于尾元素等于中间元素时,最小值有可能出现在左右两侧,如{1,0,1,1,1}或{1,1,1,0,1},所以无法使用二分查找,只能使用遍历顺序查询。
4.如果中间元素(mid)大于首位元素,则中间元素一定位于第一个数组中,则两个数组的分界点在中间元素的右边,所以low = mid。如{3,4,5,1,2}
5.如果中间元素小于首位元素,则中间元素一定位于第二个数组中,则分界点在中间元素的左边,所以high = mid。如{4,5,1,2,3}
时间复杂度为:O(nlogn)

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        //数组为0
        if(array.length == 0) return 0;
        //二分查找
        int low = 0;
        int high = array.length - 1;
        int mid = 0;
        //旋转数组的特性:
        //1,最后一个元素小于等于第一个元素
        //保证是旋转数组
        while(array[low] >= array[high]){
            //循环停止条件
            if(high - low == 1){
                mid = high;
                break;
            }
            //求中间元素
            mid = low + (high-low)/2;
            //1.第一种情况:如果头尾和中间元素相等,则无法进行二分,需要顺序执行
            if(array[low] == array[mid] && array[low] == array[high]){
                return returnMin(array,low,high);  
            }
            //2.第二种情况
            //如果中间元素大于等于第一个元素,则表明mid在第一个数组,最小值在后面一个数组
            if(array[mid] >= array[low] ){
                //缩小范围
                low = mid;
            }else{
                //如果中间元素小于第二个元素,则表示mid在第二个数组,最小元素在mid的前面
                high = mid;
            }
            
        }
        return array[mid];
    }
    
    private int returnMin(int[] a,int low,int high){
        int min = a[low];
        for(int i = low+1;i <= high;i++){
            if(min > a[i])
                min = a[i];
        }
        return min;
    }
}

当然按照题目可以直接遍历,如果是旋转数组,前一个元素大于后一个元素,则后一个元素为最小值,否则就没有进行旋转,直接返回第一个元素,时间复杂度:O(n)。这里不推荐使用这种方法,因为该题目想考察的就是二分查找的应用。

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        int n = array.length;
        if(n == 0) return 0;
        for(int i = 0;i < n - 1;i++){
            if(array[i] > array[i+1])
                return array[i+1];
        }
        return array[0];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值