1.Suppose an array sorted in ascending order 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.
分析:考虑该数组中的元素不重复,且数组为上升数组的旋转数组。
首先,考虑边界问题:
1.数组大小为0或者1的特殊情况;
2.使用二分法,判断nums[mid]与nums[left] 和 nums[right] 的关系。
在while(left < right) 循环中,
首先判断是否(right-left==1),如果有(right-left==1),则返回二者中的最小值;
否则判断:
1)nums[mid] > nums[left] && nums[mid] > nums[right],如,3,4,5,1,2
说明mid 处于旋转数组的前半部分,极小值位于mid后面,因此,left = mid;
2)nums[mid] > nums[left] && nums[mid] < nums[right],如,1,2,3,4,5
说明整个数组都为上升数组,极小值位于mid前面,或者就为mid本身,因此,right = mid;
3)nums[mid] < nums[left], 如,4,5,1,2,3
说明mid 处于旋转数组的后半部分,极小值位于mid前面,或者就为mid本身,因此,right = mid.
由于这里说明了数组中的元素不为0,因此,省去了对nums[mid] == nums[left] 或者 nums[mid] == nums[right] 的判断。
class Solution {
public:
int findMin(vector<int>& nums) {
int n = nums.size();
if(n == 0) return -1;
if(n == 1) return nums[0];
int left = 0, right = n-1;
while(left < right){
if(right - left == 1) return min(nums[left],nums[right]);
int mid = (right-left)/2+left;
if(nums[mid] > nums[left] && nums[mid] > nums[right]) left = mid;
else if(nums[mid] > nums[left] && nums[mid] < nums[right]) right = mid;
else if(nums[mid] < nums[left]) right = mid;
}
return -1;
}
};
2.Suppose an array sorted in ascending order 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.
分析:第2题与第1题的区别是,数组中的元素有可能是重复的。
首先,考虑边界问题:
1.数组大小为0或者1的特殊情况;
2.使用二分法,判断nums[mid]与nums[left] 和 nums[right] 的关系。
在while(left < right) 循环中,
首先判断是否(right-left==1),如果有(right-left==1),则返回二者中的最小值;
否则判断:
0) 考虑特殊情况,nums[mid] == nums[left] && nums[mid] == nums[right], 如,1,0,1,1,1;1,1,0,1,
这个时候,应对nums[left...right]进行遍历。
1)nums[mid] >= nums[left] && nums[mid] > nums[right],如,3,4,5,1,2
说明mid 处于旋转数组的前半部分,极小值位于mid后面,因此,left = mid;
2)nums[mid] >= nums[left] && nums[mid] <= nums[right],如,1,2,3,4,5;1,3,3
说明整个数组都为上升数组,极小值位于mid前面,或者就为mid本身,因此,right = mid;
3)nums[mid] < nums[left], 如,4,5,1,2,3
说明mid 处于旋转数组的后半部分,极小值位于mid前面,或者就为mid本身,因此,right = mid.
由于这里说明了数组中的元素不为0,因此,省去了对nums[mid] == nums[left] 或者 nums[mid] == nums[right] 的判断。
class Solution {
public:
int findMin(vector<int>& nums) {
int n = nums.size();
if(n == 0) return -1;
if(n == 1) return nums[0];
int left = 0, right = n-1;
while(left < right){
if(right - left == 1) return min(nums[left],nums[right]);
int mid = (right-left)/2+left;
if(nums[mid] == nums[left] && nums[mid] == nums[right]){
int min = nums[left];
for(int i = left+1; i <= right; i++){
if(nums[i] < min) min = nums[i];
}
return min;
}
else if(nums[mid] >= nums[left] && nums[mid] > nums[right]) left = mid;
else if(nums[mid] >= nums[left] && nums[mid] <= nums[right]) right = mid;
else if(nums[mid] < nums[left]) right = mid;
}
return -1;
}
};