AcWing 22. 旋转数组的最小数字(二分法)

这个问题投机的做法就是将数组排序然后输出最小元素。但这种做法并不推荐,原因就不解释了。

这道题最好的做法是使用二分法。在解决这个问题前,先假设数组是一个元素互异且递增的数组。那么其中一定满足nums[n]>nums[0]。当此数组发生了旋转后,则必有nums[n]<nums[0]。此时,我们可以利用这一条件结合二分法来查找最小元素。如果nums[mid]<nums[0],则说明最小元素在mid左侧,否则说明在右侧。以此就可以逐步缩小区间直至找到最小元素。

不过,题目说明了数字中可能存在重复元素。那么有没有必要对所有的元素进行去重操作呢?答案是:如果nums[0]==nums[n]则需要对数组尾端等于nums[0]的元素进行去重操作,否则的话不需要。也就是说只要保证nums[n]<nums[0]就可以了。具体的实例可以参考题解

具体代码如下:

class Solution {
public:
    int findMin(vector<int>& nums) {
        if(nums.empty()) return -1;
        int n = nums.size() - 1;
        while(n > 0 && nums[n] == nums[0]) n--; //数组尾部去重
        if(nums[n] >= nums[0]) return nums[0]; //数组是单调的,没有发生旋转
        int lo = 0, hi = n;
        while(lo < hi){
            int mid = (lo + hi) >> 1;
            if(nums[mid] < nums[0]) hi = mid;
            else lo = mid + 1;
        }
        return nums[hi];
    }
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值