题目一:
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
Find the minimum element.
You may assume no duplicate exists in the array.
分析:
二分查找,始终确保first在第一递增部分,last在第二递增部分即可。通过判断nums[mid]的大小判断mid属于第一部分还是第二部分,然后更新first或者last,逐步缩小first和last的距离,直到它们相邻。
class Solution {
public:
int findMin(vector<int>& nums) {
if (nums[0] < nums[nums.size() - 1])//递增序列,旋转0个元素
{
return nums[0];
}
int first = 0, last = nums.size() - 1;//first始终在第一部分,last始终在第二部分
while (last - first > 1)
{
int mid = first + (last - first) / 2;
if (nums[mid] > nums[first])//mid在第一段
{
first = mid;
}
else //mid在第二段
{
last = mid;
}
}
//last和first相邻或者重合
return min(nums[first], nums[last]);
}
};
题目二:
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
Find the minimum element.
The array may contain duplicates.
分析:跟上一题不同的是数组中可能存在相同元素,要想使用二分查找还得维护“始终确保first在第一递增部分,last在第二递增部分”这个不变式。只有当nums[first] == nums[mid] == nums[last]的时候不好确定mid到底属于第一部分还是第二部分,因此没法更新first和last,这种情况只能采用顺序遍历的方式查找最小值。
class Solution {
public:
int findMin(vector<int>& nums) {
if (nums[0] < nums[nums.size() - 1])//递增序列,旋转0个元素
{
return nums[0];
}
int first = 0, last = nums.size() - 1;//first始终在第一部分,last始终在第二部分
while (last - first > 1)
{
int mid = first + (last - first) / 2;
if (nums[first] == nums[last])
{
if (nums[mid] == nums[first])
{
//遍历
return *min_element(nums.begin() + first, nums.begin() + last);
}
else if (nums[mid] > nums[first])
{
first = mid;
}
else
{
last = mid;
}
}
else //nums[first]必然大于nums[last]
{
if (nums[mid] >= nums[first]) //这里允许nums[mid] == nums[first]
{
first = mid;
}
else
{
last = mid;
}
}
}
//last和first相邻或者重合
return min(nums[first], nums[last]);
}
};