[HOT 100] 1901. 寻找峰值 ii

文章目录

      • 1. 题目链接
      • 2. 题目描述
      • 3. 题目示例
      • 4. 解题思路
      • 5. 题解代码
      • 6. 复杂度分析

1. 题目链接


1901. 寻找峰值 II - 力扣(LeetCode)


2. 题目描述


一个 2D 网格中的 峰值 是指那些 严格大于 其相邻格子(上、下、左、右)的元素。

给你一个 从 0 开始编号 的 m x n 矩阵 mat ,其中任意两个相邻格子的值都 不相同 。找出 任意一个 峰值 mat[i][j] 并 返回其位置 [i,j]

你可以假设整个矩阵周边环绕着一圈值为 -1 的格子。

要求必须写出时间复杂度为 O(m log(n))O(n log(m)) 的算法


3. 题目示例


示例 1 :

[HOT 100] 1901. 寻找峰值 ii_第1张图片

输入: mat = [[1,4],[3,2]]
输出: [0,1]
解释: 3 和 4 都是峰值,所以[1,0]和[0,1]都是可接受的答案。

示例 2 :

[HOT 100] 1901. 寻找峰值 ii_第2张图片

输入: mat = [[10,20,15],[21,30,14],[7,16,32]]
输出: [1,1]
解释: 30 和 32 都是峰值,所以[1,1]和[2,2]都是可接受的答案。

4. 解题思路


  1. 二分查找行:在行维度上通过二分法缩小搜索范围。
  2. 比较相邻行:对中间行 i,找到其最大值列 j,比较 mat[i][j] 与下一行同一列的值 mat[i+1][j]
  3. 调整搜索范围
    • 若当前行的值更大,说明峰值可能在当前行或更上面的行,向上半部分收缩。
    • 否则,峰值在下半部分,向下半部分收缩。
  4. 最终结果:二分结束时,left 指向峰值所在行,返回该行的最大值位置。

关键点分析 :

  1. 二分法优化行搜索
    • 每次将搜索范围减半,时间复杂度为 O(log n)n 为行数)。
    • 通过比较中间行与下一行的同一列值,决定峰顶的可能位置。
  2. 峰值存在的必然性
    • 矩阵中一定存在峰值(题目保证)。
    • 当某行的最大值比下一行的同一列值大时,该值所在位置可能是峰值(左右已确保最大,上下通过比较保证)。
  3. 正确性验证
    • 假设最终锁定行 left,其最大值列 j 满足:
      • mat[left][j] > mat[left+1][j](若存在下一行)。
      • 由于 j 是该行的最大值,左右相邻元素均小于它。
    • 因此,该位置即为峰值。

5. 题解代码


class Solution {
    public int[] findPeakGrid(int[][] mat) {
        int left = 0, right = mat.length - 2;
        while(left <= right){
            int i = (left + right) >>> 1;
            int j = indexOfMax(mat[i]);
            if(mat[i][j] > mat[i + 1][j]){
                right = i - 1;
            } else {
                left = i + 1;
            }
        }
        return new int[]{left, indexOfMax(mat[left])};
    }

    private int indexOfMax(int[] a){
        int idx = 0;
        for(int i = 0; i < a.length; i++){
            if(a[i] > a[idx]){
                idx = i;
            }
        }
        return idx;
    }
}

6. 复杂度分析


  • 时间复杂度O(n log n),其中 n 为行数。每次二分查找需遍历当前行的所有列(O(m)),
  • 总时间为 O(m log n)
  • 空间复杂度O(1),仅使用常数空间。

你可能感兴趣的:(算法,HOT,100)