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