思路:通过观察旋转后的序列我们发现:经过(1~n)旋转后会把最初的有序序列变成两个(旋转n次就是原始序列本身)有序序列,我们只需要找到两个有序序列的分界点,然后利用初始的顺序可以很容易得到两个序列的最小值,再取二者中最小的即可。
class Solution {
public:
int findMin(vector<int>& nums) {
int n = nums.size();
if(n==1)
return nums[0];
int k=n-1;
while(k>0&&nums[k-1]<nums[k])
k--;
int ans = min(nums[k],nums[0]);
return ans;
}
};
思路:为了找到这个峰值,我们肯定是要往数值变大的方向去的移动的(题中给出了相邻的元素不相等这个条件,要好好利用)由于题目要求我们在O(logn)限制内,所以很明显在暗示要用二分的思想。但是这里面和二分查找又不太一样,二分查找初始序列是有序的,是规律的。本题中却没有这样的条件。所以我们要去想本题中有没有什么规律可以利用的。
假如我们现在在下标i的位置,我们发现nums[i+1]>nums[i],那么我们肯定是要往右边走的,那么我们如果上一次向右移动了,下一次我们还能不能向左移动呢??显然不会啊对不对。
我们可以想象一下,你现在在爬山,你要爬到山顶,我们肯定是沿着一个上升的方向爬,直到我们不能再上升的时候是不是就到山顶了。
所以这个规律就是一旦我们往一个方向移动以后,就只能一直往这个方向移动,直到这个方向的下一个元素小于当前元素是我没呢就找到了峰值。
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int n = nums.size();
if(n==1)
return 0;
if(n==2){
if(nums[0]>nums[1])
return 0;
else
return 1;
}
//n>=3
int low=0,high = n-1;
while(low<=high){
int mid = low +(high - low)/2;
if(mid==0){
if(nums[0]>nums[1])
return 0;
else
low = mid +1;
}
else if(mid==n-1){
if(nums[n-1]>nums[n-2])
return n-1;
else
high = mid -1;
}
else{
if(nums[mid]>nums[mid-1]&&nums[mid]>nums[mid+1])
return mid;
else if(nums[mid]<nums[mid-1])
high = mid -1;
else
low = mid + 1;
}
}
return -1;
}
};