154. 寻找旋转排序数组中的最小值 II
题目描述
假设按照升序排序的数组在预先未知的某个点上进行了旋转。(例如,数组 [0,1,2,4,5,6,7]
可能变为 [4,5,6,7,0,1,2]
)。
请找出其中最小的元素。注意数组中可能存在重复的元素。
示例 1:
输入: [1,3,5]
输出: 1
示例 2:
输入: [2,2,2,0,1]
输出: 0
说明:
这道题是 寻找旋转排序数组中的最小值 的延伸题目。允许重复会影响算法的时间复杂度吗?会如何影响,为什么?
代码
class Solution {
public:
int findMin(vector<int>& nums) {
int n = nums.size();
if(n == 0)
return INT_MAX;
if(n == 1)
return nums[0];
int l = 0;
int h = n-1;
while(l <= h)
{
if(h-l == 0 || h-l == 1)
return min(nums[l],nums[h]);
else
{
//这两行代码可以去掉,程序依然正确,加上这两行代码,可以使程序在已经可以停止时及时停止
// if(nums[h] > nums[l])
// return nums[l];
//根据nums[mid]是处于前半段,还是后半段,来决定查找范围的转向
int mid = l+(h-l)/2;
//由于我们是根据nums[l],nums[h],nums[mid]之间的大小关系,来判断nums[mid]是位于前半部分,还是后
//半部分,当这个条件发生时(由旋转的特点,当由搜索范围是两段时,总会有nums[l]>=nums[h],整个前半段
//总是大于等于后半段,由这个特点,即使发生nums[l]==nums[h]!=nums[mid],我们依然能够确定nums[mid]的位置),
//我们无法判断nums[mid]的位置
if(nums[mid]==nums[l] && nums[mid]==nums[h])
{
l++;
h--;//这时不会发生遗漏,至少还有mid,这里范围已经确保至少有三个数,所以可以大胆的去掉
}
else
{
//这个条件要放在前面,因为可能出现0旋转的情况,
//或者已经是一个有序的情况,而我们要找的是最小
//元素,把这个条件放在前面,是为了向最小元素方向
//跳转
if(nums[mid]<=nums[h])
h = mid;
else if(nums[mid]>=nums[l])
l = mid;
}
}
}
return INT_MAX;
}
};