峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组 nums
,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞
。
你必须实现时间复杂度为 O(log n)
的算法来解决此问题。
示例 1:
输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。
示例 2:
输入:nums = [
1,2,1,3,5,6,4]
输出:1 或 5
解释:你的函数可以返回索引 1,其峰值元素为 2;
或者返回索引 5, 其峰值元素为 6。
提示:
1 <= nums.length <= 1000
-231 <= nums[i] <= 231 - 1
i
都有 nums[i] != nums[i + 1]
思路:二分查找,直接遍历肯定不行,时间复杂度有限制。这是学习的大佬的代码。我的多了一些判断条件。不如这个。还可以把ans优化掉,直接返回left的值。带入一个例子就能知道代码的巧妙之处,不需要mid左右两边都判断。mid一旦有加减交替就会就会记录峰值,如果mid一直减小正好在0取得峰值。一直增大也是一直记录峰值的。
int findPeakElement(int* nums, int numsSize){
int left = 0;
int right = numsSize - 1;
int ans = 0;
while(left < right){
int mid = (right + left) / 2;
if(nums[mid] < nums[mid + 1]){
left = mid + 1;
ans = left;
}
else if(nums[mid] > nums[mid + 1])
right = mid;
}
return ans;
}
一个 2D 网格中的 峰值 是指那些 严格大于 其相邻格子(上、下、左、右)的元素。
给你一个 从 0 开始编号 的 m x n
矩阵 mat
,其中任意两个相邻格子的值都 不相同 。找出 任意一个 峰值 mat[i][j]
并 返回其位置 [i,j]
。
你可以假设整个矩阵周边环绕着一圈值为 -1
的格子。
要求必须写出时间复杂度为 O(m log(n))
或 O(n log(m))
的算法
示例 1:
输入: mat = [[1,4],[3,2]] 输出: [0,1] 解释: 3 和 4 都是峰值,所以[1,0]和[0,1]都是可接受的答案。
示例 2:
输入: mat = [[10,20,15],[21,30,14],[7,16,32]] 输出: [1,1] 解释: 30 和 32 都是峰值,所以[1,1]和[2,2]都是可接受的答案。
提示:
m == mat.length
n == mat[i].length
1 <= m, n <= 500
1 <= mat[i][j] <= 105
思路:这题是上题的升级版。如果做完第一题不久就来做这题可能会踩坑。用两次二分,我就踩了。我一开始想着在一行里面用了二分,找到一行的峰值,然后在峰值所在列再二分。这样思路肯定是有问题的,一行或者一列里面峰值不止一个,而且有的峰值很大,有的峰值很小。
这题正确的思路是用二分确定一行或者一列,然后遍历找出最大值,以行为例,左右两个数肯定不用比较了,因为它是最大值,只需比较上下和当前位置的大小,如果不满足就往大的方向移动。继续二分。
原理:以行为例,由于周围有一圈-1,矩阵里面都为正,那就像一座山,中间高,四周低,按照思路来,比如已知第一行的最大值,如果它不是峰值,证明同列的第二行比它大就往大的那个方向走,找到第二行的最大值再比较,以此类推。我的讲解是顺序的,二分也一样,从中间开始,往大的方向走,因为是二分,跳的很大,可能走过头,回头就行。
必定能找到峰值,因为外圈为-1,假设没有峰值,那第一行最大值必定小于第二行的一个数,那第二行的最大值肯定大于第一行的所有数,上一句话说了。如果没有峰值,那第二行的最大值也必定小于第三行的一个数,不然它就大于周围4个数了。
以此类推,倒数第二行最大值肯定小于倒数第一行的一个数。但是倒数第一行下面是-1所以倒数第一行的最大值大于周围四个数,是峰值。
题解是看的官方的
int maxElement(int *row, int n) {
int i = 0;
for (int j = 0; j < n; j++) {
if (row[i] < row[j]) {
i = j;
}
}
return i;
}
int* findPeakGrid(int **mat, int matSize, int *matColSize, int *returnSize) {
int m = matSize, n = matColSize[0];
int low = 0, high = m - 1;
while (low <= high) {
int i = (low + high) / 2;
int j = maxElement(mat[i], n);
if (i - 1 >= 0 && mat[i][j] < mat[i - 1][j]) {
high = i - 1;
continue;
}
if (i + 1 < m && mat[i][j] < mat[i + 1][j]) {
low = i + 1;
continue;
}
int *ret = (int *)malloc(sizeof(int) * 2);
ret[0] = i;
ret[1] = j;
*returnSize = 2;
return ret;
}
*returnSize = 0;
return NULL; // impossible
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/find-a-peak-element-ii/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。