Given an m x n
integers matrix
, return the length of the longest increasing path in matrix
.
From each cell, you can either move in four directions: left, right, up, or down. You may not move diagonally or move outside the boundary (i.e., wrap-around is not allowed).
Example 1:
Input: matrix = [[9,9,4],[6,6,8],[2,1,1]]
Output: 4
Explanation: The longest increasing path is [1, 2, 6, 9]
.
Example 2:
Input: matrix = [[3,4,5],[3,2,6],[2,2,1]]
Output: 4
Explanation: The longest increasing path is [3, 4, 5, 6]
. Moving diagonally is not allowed.
Example 3:
Input: matrix = [[1]] Output: 1
Constraints:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 200
0 <= matrix[i][j] <= 231 - 1
又是一题hard的题,之所以为hard是因为不容易发现可以用拓扑排序(Topological Sort)法。仔细读两遍题目会发现其实它符合拓扑排序的特性,路径是递增的说明矩阵的点是有前后顺序关系的,如果把矩阵看成一个图,矩阵中的一个点跟值比它大的邻居(上下左右)点存在先后顺序关系形成一条有向边,边从小数字指向大数字,因此大的数字的入度加1。遍历整个矩阵遇到满足条件的边,计算大数入度,由于矩阵中的点只可能跟邻居点构成边,因此不需要另外创建一个图。
有了每个点的入度值后,就可以用BFS来剔除边。首先把所有入度值为的0都放入一个队列,然后循环处理直到队列为空,每次循环都把队列中的所有点都取出,再把它们满足条件的邻居点的入度值减1并把入度值变为0的点放入队列中,每循环一次步数加1,如此循环直到队列为空,最后总步数就是最长递增路径。
class Solution:
def longestIncreasingPath(self, matrix: List[List[int]]) -> int:
m, n = len(matrix), len(matrix[0])
indegree = [[0] * n for i in range(m)]
for i in range(m):
for j in range(n):
for (r, c) in ((i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)):
if r >= 0 and r < m and c >= 0 and c < n and matrix[r][c] < matrix[i][j]:
indegree[i][j] += 1
q = deque()
for i in range(m):
for j in range(n):
if indegree[i][j] == 0:
q.append((i, j))
res = 0
while q:
qsize = len(q)
for cnt in range(qsize):
(i, j) = q.popleft()
for (r, c) in ((i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)):
if r >= 0 and r < m and c >= 0 and c < n and matrix[r][c] > matrix[i][j]:
indegree[r][c] -= 1
if indegree[r][c] == 0:
q.append((r,c))
res += 1
return res