题目描述
解题思路
- 如何二分? 确保 结果集只在一个区间中。
- nums[mid] > nums[left] . ans包含于 left + [mid+1, right)
- nums[mid] < nums[left] . ans 包含于 [left, mid) + mid
- nums[mid] > nums[right]. ans 包含于 [mid+1, right)
- nums[mid] < nums[right]. ans 包含于 [left, mid) + mid
- 区间选择,区间二分后 取左区间 还是 右区间?
需要注意的是mid始终有可能是最小值。我们在二分过程中,不能排除 Mid是最小值的可能性。
注意点:中位位置是 左中位
两种base case
一个元素(奇数)
例如数组 [3] 。此时mid和right(or right-1)重合,应指向3
两个元素(偶数)
例如数据 [4,3]。此时mid应指向4,right(or right-1)指向3。即mid指向左中位。
左闭右开
此时
- base case => 两个元素
- 中位位置 => 左中位
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
vector<int>& nums = rotateArray;
int n = nums.size();
int left=0, right = n; // init interval [0, n)
while(left<right) {
int mid = left+(right-1-left)/2;
if(nums[mid]<nums[right-1]) {
right = mid+1; // 区间shrink to [left, mid+1)。 此处不可排除mid,mid仍有可能是最小值
} else if(nums[mid]>nums[right-1]) {
left = mid+1; // 区间shrink to [mid+1, right).
} else if(nums[mid]==nums[right-1]) {
right--; // 区间shrink to [left, right-1)
}
}
return nums[left];
}
};
左闭右闭
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
vector<int>& nums = rotateArray;
int n = nums.size();
int left=0, right = n-1; // init interval [0, n-1]
while(left<right-1) {
int mid = left+(right-left)/2;
if(nums[mid]<nums[right]) {
right = mid; // interval shrink to [left, mid]. mid is possible to be the least.
} else if(nums[mid]>nums[right]) {
left = mid+1; // interval shrink to [mid+1, right]
} else if(nums[mid]==nums[right]) {
right--; // interval shrink to [left, right-1]
}
}
return nums[left];
}
};