LeetCode 二分查找专题 153 旋转数组最小值 题解

题目详情

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

请找出其中最小的元素。

你可以假设数组中不存在重复元素。
示例 1:

输入: [3,4,5,1,2]
输出: 1
示例 2:

输入: [4,5,6,7,0,1,2]
输出: 0

题目分析

关于二分查找,我们首先要确定的是查询操作是否适合2分查找,即每次选择中间的数之后,是否能从当前数和左右边界的数来判断目标数在前还是后,即是否从中间的数能找到规律。
同时一个比较重要的点在于,新的区间是否包含m,这个比较关键。
最后一个需要考虑的事是,当最终的区间收缩到2时,是不是会出现不一样的结果,如果不一样,就得修改一下终止的条件,然后进行判断。

这里该题的旋转简直是扯淡,想了半天都没弄懂旋转是什么意思,这里就理解成选择一个点,然后从这个点把整个数列切割成两个部分,然后交换。
这里要注意整个数列一开始是升序的,再进行交换之后,两个子数列也是分别升序的。
也就是说,我们的数组实际上是两个升序数列构成,同时一个数列还一定全部小于另外一个数列。

那么我们取中间数的话可能有两种情况:
在这里插入图片描述
第一种情况:我们可以看到,此时二分查找的中间值m一定是在2里的,那么此时中间值m有什么特性呢?
在2里,该中间值m是大于2的最前面的元素,因为在原来的升序数组中,2的位置在1后面,所以2的值都全部大于1,所以中间值m一定大于1的所有,也就等价于中间值m大于1的最右侧的元素。所以当上图的状态,中间值m大于l和h的值。

在这里插入图片描述
第二种情况:也和第一种情况的分析是差不多的,这里的情况是中间值m同时小于l和h的值。

如此,我们便找到中间值所存在的规律。不过除了这个,当然还有一个特殊情况,那就是,原数列切割的点在边界上,等于原数列没有变化。
在这里插入图片描述
此时就会出现第三种特殊的情况,即中间值m大于l的值却小于h的值,那么此时就得单独考虑,直接返回l的值就好。

综上,基本上代码逻辑就出来了,然后当最终区间缩小到2时,会发现它的逻辑和之前的不一样,所以这里就将判断条件放到区间为2,然后将区间为2的最小值给返回,。
然后对于是否新区间包含m,这里显然是包含的。

代码实现

class Solution {
    public int findMin(int[] nums) {
        if(nums.length<2){
            return nums[0];
        }
        int l=0,h = nums.length-1;
        while(l<h-1){
            int m = l+(h-l)/2;
            if(nums[m]>nums[l]&&nums[m]>nums[h]){
                l = m;
            }
            else if(nums[m]<nums[l]&&nums[m]<nums[h]) {
                h = m;
            }
            else{
                return nums[0];
            }
            //当是大于前小于后时
        }

        return nums[l]>nums[h]?nums[h]:nums[l];

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值