寻找峰值Ⅱ(LeetCode日记)

发布时间:2023年12月22日

LeetCode-1901-寻找峰值Ⅱ

题目信息:

一个 2D 网格中的 峰值 是指那些 严格大于 其相邻格子(上、下、左、右)的元素。
给你一个 从 0 开始编号 的 m x n m x n mxn 矩阵 m a t mat mat ,其中任意两个相邻格子的值都 不相同 。找出 任意一个 峰值 m a t [ i ] [ j ] mat[i][j] mat[i][j] 并 返回其位置 [ i , j ] [i,j] [i,j]
你可以假设整个矩阵周边环绕着一圈值为 -1 的格子。
要求必须写出时间复杂度为 O ( m l o g ( n ) ) O(m log(n)) O(mlog(n)) O ( n l o g ( m ) ) O(n log(m)) O(nlog(m)) 的算法
在这里插入图片描述
在这里插入图片描述

提示:

  • m = = m a t . l e n g t h m == mat.length m==mat.length
  • n = = m a t [ i ] . l e n g t h n == mat[i].length n==mat[i].length
  • 1 < = m , n < = 500 1 <= m, n <= 500 1<=m,n<=500
  • 1 < = m a t [ i ] [ j ] < = 105 1 <= mat[i][j] <= 105 1<=mat[i][j]<=105
  • 任意两个相邻元素均不相等

题解

方法:二分法;
m m m n n n 分别为 m a t mat mat 的行数和列数。首先对于一维数组,因为任意两个相邻的格子的值都不相同,所以它的最大值必定是该一维数组的峰值。基于这一点,我们可以只考虑每一行的最大值,记第 i i i 行的最大值为第 j i j_i ji?列元素,如果 m a t [ i ] [ j i ] > m a t [ i ? 1 ] [ j i ] mat[i][j_i]>mat[i?1][j_i] mat[i][ji?]>mat[i?1][ji?] m a t [ i ] [ j i ] > m a t [ i + 1 ] [ j i ] mat[i][j_i]>mat[i+1][j_i] mat[i][ji?]>mat[i+1][ji?](对于数组越界的情况,取 ? 1 ?1 ?1 值),那么 ( i , j i ) (i,j_i) (i,ji?)即为结果。
对于题目给定的条件,是否一定存在峰值呢?答案是肯定的。证明可以采用反证法:

如果不存在峰值,根据题目给定的条件,我们知道第0 行的最大值比它上面的格子(值为 ?1)大,那么初始时有 i = 0 i=0 i=0 行的最大值满足比上面格子大的条件。如果第 i i i行的最大值满足比它上面的格子大这一条件,那么根据不存在峰值的前提,我们有 m a t [ i ] [ j i ] < m a t [ i + 1 ] [ j i ] mat[i][ji]<mat[i+1][j_i] mat[i][ji]<mat[i+1][ji?],而 m a t [ i + 1 ] [ j i + 1 ] ≥ m a t [ i + 1 ] [ j i ] > m a t [ i ] [ j i ] ≥ m a t [ i ] [ j i + 1 ] mat[i+1][j_i+1]≥mat[i+1][j_i]>mat[i][j_i]≥mat[i][j_{i+1}] mat[i+1][ji?+1]mat[i+1][ji?]>mat[i][ji?]mat[i][ji+1?],从而我们有 m a t [ i + 1 ] [ j i + 1 ] > m a t [ i ] [ j i + 1 ] mat[i+1][j_i+1]>mat[i][j_{i+1}] mat[i+1][ji?+1]>mat[i][ji+1?],即 i + 1 i+1 i+1也满足条件。基于以上推导,使用数学归纳法,当 i = m ? 1 i=m?1 i=m?1时,有 m a t [ m ? 1 ] [ j m ? 1 ] > m a t [ m ? 2 ] [ j m ? 1 ] mat[m?1][j_{m?1}]>mat[m?2][j_{m?1}] mat[m?1][jm?1?]>mat[m?2][jm?1?],而下面的格子值为 ? 1 -1 ?1,显然 ( m ? 1 , j m ? 1 ) (m?1,j_{m?1}) (m?1,jm?1?) 为峰值,与不存在峰值矛盾。

根据以上证明,我们也可以得出这样一个结论,即如果 i 1 i_1 i1?行的最大值比它上面的格子大, i 2 i_2 i2?行比它下面的格子大,且 i 1 ≤ i 2 i_1 \leq i_2 i1?i2? ,那么 [ i 1 , i 2 ] [i_1,i_2] [i1?,i2?]之间一定存在峰值。基于这个结论,我们可以使用二分法来求解问题,初始时 l o w = 0 , h i g h = m ? 1 low=0,high=m-1 low=0,high=m?1:

  1. i = ? l o w + h i g h 2 ? i=\lfloor \frac{low+high}{2} \rfloor i=?2low+high?? , 第 i i i行的最大值为第 j j j列。
  2. 如果 m a t [ i ] [ j ] < m a t [ i ? 1 ] [ j ] mat[i][j] < mat[i-1][j] mat[i][j]<mat[i?1][j] ,那么令 h i g h = i ? 1 high = i-1 high=i?1,继续步骤1。
  3. 如果 m a t [ i ] [ j ] < m a t [ i + 1 ] [ j ] mat[i][j] < mat[i+1][j] mat[i][j]<mat[i+1][j] ,那么令 l o w = i + 1 low = i+1 low=i+1,继续步骤1。
  4. 返回 ( i , j ) (i,j) (i,j)为结果。

使用了这样的方法,我们的时间复杂度为 O ( n l o g m ) O(nlog_m) O(nlogm?)

代码实现 ( P y t h o n ) (Python) (Python)
class Solution:
    def findPeakGrid(self, mat: List[List[int]]) -> List[int]:
        m = len(mat)
        #n = len(mat[0])
        low = 0
        high = m-1
        while low <= high:
            i = (low + high)//2 
            j = mat[i].index(max(mat[i]))
            if i-1>=0 and mat[i][j] < mat[i-1][j]:
                high = i-1
                continue
            if i+1 < m and mat[i][j] < mat[i+1][j]:
                low = i + 1
                continue
            return [i,j]
        return None            

题记:


  • 研究生在读,我会尽量保持LeetCode每日一题的思路和代码输出。希望大家多多支持。
  • 水平有限,希望各位大佬能够批评指正。您的教诲是我进步的船帆。
  • 希望各位跟我一样的小白能跟我一起参与到做题和讨论中来。共同进步是我所能期盼的最高愿想。
  • 您的点赞和关注是我坚持分享的动力泉源,希望能将这件简单平凡的事一直做下去。感谢大家。

文章来源:https://blog.csdn.net/weixin_52242569/article/details/135084725
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。