題目一:
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]);
}
};