HOT67-寻找旋转排序数组中的最小值
leetcode原题链接:寻找旋转排序数组中的最小值
题目描述
已知一个长度为 n
的数组,预先按照升序排列,经由 1
到 n
次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7]
在变化后可能得到:
- 若旋转
4
次,则可以得到[4,5,6,7,0,1,2]
- 若旋转
7
次,则可以得到[0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], ..., a[n-1]]
旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]]
。
给你一个元素值 互不相同 的数组 nums
,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
你必须设计一个时间复杂度为 O(log n)
的算法解决此问题。
示例 1:
输入:nums = [3,4,5,1,2] 输出:1 解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
示例 2:
输入:nums = [4,5,6,7,0,1,2] 输出:0 解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。
示例 3:
输入:nums = [11,13,15,17] 输出:11 解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。
提示:
n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums
中的所有整数 互不相同nums
原来是一个升序排序的数组,并进行了1
至n
次旋转
解题方法:二分查找。旋转数组中的最小值可能分布如下
1. 数组未发生旋转,整体升序,即nums[left] <= nums[right],则最小值为nums[left]
2. 数组发生旋转,则nums[left] > nums[right,则最小值位于右半段的第一个元素。
C++代码
#include <iostream>
#include <vector>
class Solution {
public:
int findMin(std::vector<int>& nums) {
int n = nums.size();
int left = 0;
int right = n - 1;
while (left <= right) {
if (nums[left] <= nums[right]) { //当前数组整体有序,等于是因为考虑到left和right指向同一个元素
return nums[left];
}
int mid = (left + right) / 2;
if (mid > 0 && nums[mid] < nums[mid - 1]) { //mid在左右交界的地方(即右半部分的第一个节点)
return nums[mid];
} else if (nums[mid] >= nums[left]) { //当前mid在左边升序部分,因为mid可能等于left,例如right=left+1的时候
left = mid + 1;//mid必然会是最终解,因为mid在左半部分
} else if (nums[mid] < nums[right]) { //当前mid在右边升序部分
right = mid - 1;//mid必然是右边节点(非第一个节点)
}
}
return -1;
}
};