- 寻找旋转排序数组中的最小值 https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/
题目的意思是让我们求解其中的旋转后的数组中的元素的最小值,当然数组也可能是没有旋转,也就是说数组是有序的。其实这个题目暴力解答的话时间复杂度也只有O(n)。首先看下面暴力解答的的代码:
也就是直接遍历整个数组去找到其中的最小值
class Solution {
public:
int minArray(vector<int>& numbers) {
if(numbers.empty()) return 0;
int min = INT_MAX;
for(int i =0; i < numbers.size(); i++) {
if(numbers[i] < min) {
min = numbers[i];
}
}
return min;
}
};
但是本题目有一个更加简便的方法,但是这个题目的难度也不足以构成一道hard的题目,下面讲讲基于二分查找的思路:
首先我们要知道如果当前的数组没有被旋转,那么就是一个有序的序列,那么必然满足:nums[length - 1] > nums[0]。成立的,直接返回对应的nums[0]即可!旋转之后的话,也是有规律可以找到的,首先旋转之后那么当前的首元素的值必然大于尾部元素的值,否则数组就是没有被旋转,然后在旋转后得到的序列的中间必然有一个点处满足于当前的元素小于前面的元素即: nums[mid] < nums[mid - 1]这个mid就是我们要找的元素,因为本身局部有序性应该是满足:num[mid] > nums[mid - 1]的,维度只有我们需要查找的点满足。当然上面的条件也可以写成:nums[mid]>nums[mid+1]这个时候就是返回对应的nums[mid]即可!看下面的图片比较直观!
那么如何不断的缩小判断的区间呢?只要当前的nums[mid] > nums[0]的时候,就更新到mid的右侧来判断,繁殖则来到左侧判断即可!
思路明确了,实现的代码如下:
class Solution {
public:
int findMin(vector<int>& nums) {
if(nums.size() == 1) return nums[0];
int left =0;
int right = nums.size() - 1;
if(nums[right] > nums[left])
{ //代表就是有序的直接返回第一个元素即可
return nums[0];
}
// 23456 01
while(right >= left){
int mid = left + (right - left) / 2;
if(nums[mid] > nums[mid + 1] ) {
return nums[mid+1];
}
if(nums[mid] < nums[mid - 1]) {
return nums[mid];
}
//找到了对应的中间节点。
if(nums[mid] > nums[0]) {
left = mid + 1;
} else {
right = mid - 1;
}
//使用nums[0]作为基准来判断需要往那边增加
}
return -1;
}
};