方法一:二分查找:时间O(logn),空间O(1)
题解:比较 mid 值和 right 的值分三种情况
- 若num[mid] < num[right],则 mid 和 right 处于同一个递增序列,也就是可以忽略右半区间。让right = mid,注意这里不能确定mid 处是不是最小值,因此不能是right = mid - 1
- 若num[left] > num[right],则 mid 和 right 处于不同递增区间,[left, mid]之间不可能存在最小值,因此可以忽略左半区间,让 left = mid + 1,这里可以直接让left = mid + 1。
- 若num[mid] == num[right],此时不能确定[left, right]之间是否存在最小值,因此right - -,下面只要证明right - -之后[left, right]之间存在最小值:设最小值位置为 x,若 x < right 则right - -后正确。若 x = right 则 num[mid] = num[right] = num[x] 则right - - 之后也正确
这里不用 left 作为参照是因为:无法确定第一次比较时,left 是在哪一个区间内,因此无法移动left 和 right 位置
class Solution {
public:
int minArray(vector<int>& numbers)
{
int left = 0, right = numbers.size() - 1;
while (left <= right)
{
int mid = left + ((right - left) >> 1);
// 1.说明可以忽略右区间
if (numbers[mid] > numbers[right])
{
left = mid + 1;
}
// 2.说明可以忽略左区间
else if (numbers[mid] < numbers[right])
{
right = mid;
}
// 3.不能判断mid 和 right中间是否存在最小值,因此right--
else
{
right--;
}
}
return numbers[left];
}
};