1901.寻找峰值
题目链接:1901.寻找峰值
题目:
一个 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
- 任意两个相邻元素均不相等.
思路:
看完题目先看数据范围,所有数据都是正数,题目要求算法的时间复杂度为\(O(m log(n))或O(n log(m))\),根据这个时间复杂度大致判断,我们可以对一行或者一列做遍历操作,但是选择这个行或列的时候应该需要复杂度为\(O(log)\)的算法,既然是寻找峰顶,我们可以想到二分来寻找,其时间复杂度为\(O(log)\),那么我们现在需要想怎么做。
如图所示,对于每一个峰值来说,他相对于这一行的所有元素肯定是最大的。当我们找到这行最大的元素,我们判断他是不是峰值,如果他小于他下面的元素,那么他下面几行里一定包括一个峰顶。
同理,如果他小于他上面的元素,那么他上面的几行里一定包括一个峰顶。
若上诉两个情况都不成立,那么他就是峰顶。
代码:
class Solution {
int get_j(vector<int> &a) {
return max_element(a.begin(), a.end()) - a.begin();
}
public:
vector<int> findPeakGrid(vector<vector<int>> &mat) {
int l = 0, r = mat.size() - 2;
while (l <= r) {
int i = l + (r - l) / 2;
int j = get_j(mat[i]);
if (mat[i][j] > mat[i + 1][j]) {
r = i - 1;
} else {
l = i + 1;
}
}
return {l, get_j(mat[l])};
}
};