剑指 offer acwing 22 旋转数组的最小数字 (二分)

题面

在这里插入图片描述

题解

  1. 题中说输入的是一个上升序列的旋转序列 ,就是比如一个上升序列是 1 2 3 4 5
    题中就可以输入4 5 1 2 3,然后让你找最小的。 (序列中会有重复的数字)
  1. 我们以横坐标表示序列的下标,纵坐标表示序列值的大小
    在这里插入图片描述
    就会得出这样的图(前面的一段区间是在后边一段的上边的,旋转得到)我们发现除了最后水平的一段(黑色水平那段)之外,其余部分满足二分性质:竖直虚线左边的数满足 nums[i]≥nums[0];而竖直虚线右边的数不满足这个条件。分界点就是整个数组的最小值。
  1. 所以我们先将最后水平的一段删除即可。另外,不要忘记处理数组完全单调的特殊情况:当我们删除最后水平的一段之后,如果剩下的最后一个数大于等于第一个数,则说明数组完全单调。
  1. 二分的时间复杂度是 O(logn),删除最后水平一段的时间复杂度最坏是 O(n),所以总时间复杂度是 O(n)。

代码

class Solution {
    
    
public:
    int findMin(vector<int>& nums) {
    
    
        
        int 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 l=0,r=n;
        while(l<r){
    
    
            int mid=(l+r)>>1;
            if(nums[mid]<nums[0]) r=mid;
            else l=mid+1;
        }
        return nums[l];
    }
};

猜你喜欢

转载自blog.csdn.net/qq_44791484/article/details/114901880