描述
给定一个长度为n的数组nums,请你找到峰值并返回其索引。数组可能包含多个峰值,在这种情况下,返回任何一个所在位置即可。
1.峰值元素是指其值严格大于左右相邻值的元素。严格大于即不能有等于
2.假设 nums[-1] = nums[n] = -\infty−∞
3.对于所有有效的 i 都有 nums[i] != nums[i + 1]
4.你可以使用O(logN)的时间复杂度实现此问题吗?
数据范围:
1 \le nums.length \le 2\times 10^5 \1≤nums.length≤2×105
-2^{31}<= nums[i] <= 2^{31} - 1−231<=nums[i]<=231−1
如输入[2,4,1,2,7,8,4]时,会形成两个山峰,一个是索引为1,峰值为4的山峰,另一个是索引为5,峰值为8的山峰,如下图所示:
示例1
输入:
[2,4,1,2,7,8,4]复制
返回值:
1复制
说明:
4和8都是峰值元素,返回4的索引1或者8的索引5都可以
示例2
输入:
[1,2,3,1]复制
返回值:
2复制
说明:
3 是峰值元素,返回其索引 2
本题用暴力解法也能解
用二分的话需要观察其中的规律,因为题目假设了nums[-1] = nums[n] = -\infty−∞,因此使用二分法有上升趋势的一边一定存在峰值,且峰值为right
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param nums int整型vector * @return int整型 */ /*int findPeakElement(vector<int>& nums) { // write code here int n = nums.size(); if (n == 1) return 0; if (n == 2) { if (nums[0] > nums[1]) { return 0; } else { return 1; } } if (nums[0] > nums[1]) { return 0; } int left = 0; int right = n - 1; for (int i = 1; i < n-1; i++) { if (nums[i] > nums[i-1] && nums[i] > nums[i+1]) { return i; } } if (nums[n-1] > nums[n-2]) { return n-1; } return -1; }*/ int findPeakElement(vector<int>& nums) { int n = nums.size(); int left = 0; int right = n - 1; while(left < right) { int mid = (right-left)/2 + left; //cout <<mid << endl; if (nums[mid] > nums[mid-1] && nums[mid] > nums[mid+1]) { return mid; } if (nums[mid] > nums[mid+1]) { right = mid; } else { left = mid + 1; } } return right; } };