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.
在一个被翻转的有序数组中找到最小元素。考虑没有重复元素的情况:
O(n)
class Solution {
public:
int findMin(vector<int> &num) {
int head = 0,end = num.size()-1;
if(num[end]<num[head]){
while(num[end]>num[end-1]&&end>0){
end--;
}
return num[end];
}
else{
return num[head];
}
}
};
O(lgn)
因为数组被分成前后两部分,并且前半部分的数值总比后半部分大。使用二叉查找法,看mid位置的值,如果比数组最后一个元素还大,那这个置肯定位于大数部分,反之则位于小数部分。这样步步逼近,就可以找到最小值。
class Solution{
public:
int findMin(vector<int> &num){
return find(num,0,num.size()-1);
}
int find(vector<int> num, int left, int right){
if (num[left] <= num[right]) return num[left];
int mid = (left + right) >> 1;
if (num[mid] > num[right])
return find(num, mid + 1, right);
else
return find(num,left,mid);
}
};
Follow up for "Find Minimum in Rotated Sorted Array":
What if duplicates are allowed?Would this affect the run-time complexity? How and why?
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.
现在考虑第二题,有重复元素出现的情况。如果有重复元素出现,那么翻转处有可能位于重复元素的范围内,如果这样的话则需要将前后两端的重复元素去掉,将左右两个游标分别++和--。这里有一点需要特别注意的是,当右侧游标--时,right元素一定要比right-1元素要大,否则就不能--。如果数组中剩下的全部是重复元素,则返回重复元素。剩下的操作和第一题一样。
class Solution {
public:
int findMin(vector<int> &num) {
return find(num, 0, num.size() - 1);
}
int find(vector<int> num, int left, int right){
while (left < right && num[left] == num[right]&&num[right-1] <= num[right]){
left++;
right--;
}
if (left >= right){
return num[left];
}
if (num[left] < num[right]) return num[left];
int mid = (left + right) >> 1;
if (num[mid] > num[right])
return find(num, mid + 1, right);
else
return find(num, left, mid);
}
};