寻找峰值Ⅱ(LeetCode日记)
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:
- 另 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列。
- 如果 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。
- 如果 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。
- 返回 ( 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
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!