day18:22. 旋转数组的最小数字(二分法)LeetCode154 寻找旋转数组的最小值Ⅱ

问题描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个升序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
数组可能包含重复项。
注意:数组内所含元素非负,若数组大小为0,请返回-1。
样例

  • 输入:nums=[2,2,2,0,1]
  • 输出:0

巧妙地使用了二分法,附上大佬的题解过程,乍一看,好像不好理解,仔细一看,发现很巧妙。首先是去掉最后一段不满足单调递增的数组部分,其余部分都是满足二分条件,最特殊的例子比如[2,0,1,2,2]除去最后那段重复的部分,[2,0,1]这部分就满足二分条件,nums[i]>=nums[0],以0为分界点,有半段不满足,这样使用二分将 r 所在位置找出来即可。特殊情况输入的例子本来就是递增数列,那么只需要将nums[0]输出即可。旋转数组之后最小值在后半段。需要看mid在数组的左半段还是右半段。

class Solution {
public:
    int findMin(vector<int>& nums) {
        int l=0,n=nums.size()-1;
        if(n<0) return -1;
        while(n>0&&nums[n]==nums[0]) n--;
        if(nums[n]>nums[0]) return nums[0];
        int r=n;
        while(l<r)
        {
            int mid=(r+l)/2;
            if(nums[mid]<nums[0]) r=mid; //mid在后半段,有可能是等于mid
            else l=mid+1;//说明mid在左半段
        }
        return nums[r];
    }
};

中间部分变换成下面的代码需要注意加上等号,因为这样一开始判断的是mid在左边段,左半段有可能是样例[3,3,1,2]所显示的那样,如果去掉等号返回的结果是3,而不是1。

		while(l<r)
        {
            int mid=(l+r)>>1;
            if(rotateArray[0]<=rotateArray[mid]) l=mid+1;
            else r=mid;
        }

类似的题目【搜索旋转排序数组 II】有重复值和无重复值需要注意。这个题目是寻找目标值,目标值所在的位置可以是前半段也可以是后半段,因此需要分两种情况讨论。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值