【算法】二分算法——寻找旋转排序数组中的最小值

题解:寻找旋转排序数组中的最小值(二分算法)

1.题目

题目链接:LINK
在这里插入图片描述

2.暴力求解

思路:挨个便利,看哪里突然变小了就返回该数值即可。当然,如果没有变小的情况可以返回nums[0]位置。

class Solution {
public:
    //暴力求解思路
    int findMin(vector<int>& nums) 
    {
        int fornum = nums[0];
        for(size_t i = 1; i < nums.size(); i++)
        {
            if(nums[i] < fornum) return nums[i];

            fornum = nums[i];
        }

        return nums[0];
    }
};

3.二分算法

其实这个题目有鲜明的二段性

这里我们以D点作为分界值来区分:
在这里插入图片描述
在这里插入图片描述

参考代码如下:

class Solution {
public:
    //二分算法
    int findMin(vector<int>& nums) 
    {
        int left = 0, right = nums.size() - 1;
        int D = nums.size() - 1;
        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] <= nums[D]) right = mid;
            else left = mid + 1;
        }

        return nums[left];
    }
};

当然,这个题我们也可以用nums[0]来作为参考点区分两段数组。
在这里插入图片描述
如果mid >= A , left = mid;
如果mid < A , right = mid - 1;

特殊情况:
然后就可以写出这样的代码:

class Solution {
public:
    //二分算法
    int findMin(vector<int>& nums) 
    {
        int left = 0, right = nums.size() - 1;

        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] < nums[0]) right = mid;
            else left = mid + 1;
        }

        //特殊情况做处理
        // if(nums.size() >=2 && nums[left-1] < nums[left]) return nums[0];

        return nums[left];
    }
};

在这里插入图片描述

但是有个问题:就是上面数组,可能会出现这种情况:
在这里插入图片描述
也就是我们代码需要找的C点直接没有了,不存在了。实际上这种情况下答案要转换为我们对应的A点,但是你的代码是要的B点。

因此我们可以加上一条特殊判断就行:

class Solution {
public:
    //二分算法
    int findMin(vector<int>& nums) 
    {
        int left = 0, right = nums.size() - 1;

        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] < nums[0]) right = mid;
            else left = mid + 1;
        }

        //特殊情况做处理
        if(nums.size() >=2 && nums[left-1] < nums[left]) return nums[0];

        return nums[left];
    }
};

4.思考:为什么用A作为界点和用D作为界点不一样,一个需要特殊处理,另一个则不需要???

我们不妨就拿着那个报错的特殊用例来看,假设用A作分界点(用数组第一个值作为划分依据)和用D(用数组最后一个数字作为划分依据)作为分界点的方法都对下面这组数据进行求值:
在这里插入图片描述
我们发现两种方法有着不同的划分方式:
在这里插入图片描述

说白了,用数组第一个值作为划分依据的方法直接把我们要求的值划没了,但是另一种划分方法巧妙的把这种特殊情况归类到了我们的求值范围内。

换言之,用A作为界点只适用于下图两条线都存在的情况(如果不做特殊处理)
在这里插入图片描述
而用D点作为划分依据则适用于所有情况:
在这里插入图片描述

5.总结

这个题倒是不难,但是到底用哪个值作为界点值得我们思考。


EOF

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值