Find Minumu in Rotated Sorted Array

https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/

对于一个有序数组,将其元素以某一个元素为轴进行旋转,比如[0,1,2,3,4,5,6,7]可能会变成[4,5,6,7,0,1,2,3]
求这个经过旋转的数组的最小值,这里假设数组中没有重复值

二分查找

  • 可以看到,对于一个经过旋转的数组,[4,5,6,7,0,1,2,3] 其最小元素的左右两边都是有序的,如果对于某个元素,存在 nums[i] > nums[i-1],那么最小的元素就在 i 处
  • 因此,可以通过二分查找来解决,mi = (lo+hi)>>1,如果nums[mi] < nums[hi],则说明从 mi - hi之间都是有序的,因此逆序存在左边,因此需要把hi往左压缩
  • 反之,则说明逆序在右边,即左边是有序的,因此需要把lo往右压缩
class Solution {
public:
    int findMin(vector<int>& nums) {
        int lo = 0, hi = nums.size()-1;
        while(lo < hi)
        {
            int mi = (lo + hi)>>1;
            if(nums[mi] < nums[hi])
                hi = mi;
            else
                lo = mi+1;
        }
        return nums[lo];
    }
};

时间复杂度 \(O(logN)\)


求这样一个数组的最大值

class Solution {
public:
    int findMin(vector<int>& nums) {
        int lo = 0, hi = nums.size()-1;
        while(lo < hi)
        {
            int mi = (lo + hi)>>1;
            if(nums[mi] < nums[hi])
                hi = mi-1;
            else
                lo = mi;
        }
        return nums[lo];
    }
};

  • 实际上,上面两个算法求的是逆序对的位置,而逆序对的位置可以用左边的元素来表示,也可以用右边的元素来表示,左边的元素就是最大值,右边的元素的就是最小值;
  • 因此,如果要求最大值,我们要把 lo 和 hi 尽可能往左靠,即 lo = mi, hi = mi-1
  • 如果要求最小值,我们要把 lo 和 hi 尽可能往右靠,即 lo = mi + 1, hi = mi

相关问题,如果数组中存在相同的元素 https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii

posted @ 2020-03-19 21:48  默写年华  阅读(106)  评论(0编辑  收藏  举报