1. 问题描述:
给定一个 m x n 整数矩阵 matrix ,找出其中最长递增路径的长度。
对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。
示例 1:
输入:matrix = [[9,9,4],[6,6,8],[2,1,1]]
输出:4
解释:最长递增路径为 [1, 2, 6, 9]。
输入:matrix = [[3,4,5],[3,2,6],[2,2,1]]
输出:4
解释:最长递增路径是 [3, 4, 5, 6]。注意不允许在对角线方向上移动。
示例 3:
输入:matrix = [[1]]
输出:1
提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 200
0 <= matrix[i][j] <= 2^31 - 1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix
2. 思路分析:
分析题目可以知道我们可以枚举矩阵中的所有位置并且以当前位置作为起点开始dfs搜索,这样可以求解以当前位置(i, j)为起点出发的最长递增路径,因为每一个格子都有上下左右四种走法,而且矩阵最大的行数和列数最大为200所以最多可能有4 ^ 200种尝试的可能所以使用一般的dfs搜索肯定是会超时的我们需要使用记忆化的搜索减少重复性的递归,因为当你走到一个格子的时候之前这个位置已经被求解过了那么就没有必要往下再求解了(之前已经对这个格子搜素完全部的路径并且当前位置的值就是以当前起点的最长递增路径),因为从当前这个位置往下走又是和之前一样重复性的递归,所以我们可以使用一个二维数组或者列表记录一下已经求解过的位置,这样可以避免重复子问题的求解,减小时间复杂度。题目中说了路径是完全递增的,所以在dfs搜索的过程中是不存在环的,所以最终路径的起点与终点是不存在环的所以不用标记数组或者列表。
3. 代码如下:
from typing import List
class Solution:
pos = [[0, 1], [0, -1], [1, 0], [-1, 0]]
r, c = 0, 0
# f为记忆化列表
def dp(self, x: int, y: int, f: List[List[int]], w: List[List[int]]):
# 当前位置为起点对应的最长递增路径
v = f[x][y]
if v != -1: return v
v = 1
for i in range(4):
x1, y1 = x + self.pos[i][0], y + self.pos[i][1]
# 尝试四个可以走的方向
if 0 <= x1 < self.r and 0 <= y1 < self.c and w[x1][y1] > w[x][y]:
v = max(v, self.dp(x1, y1, f, w) + 1)
# 更新记忆化列表的值
f[x][y] = v
return v
def longestIncreasingPath(self, matrix: List[List[int]]) -> int:
r, c = len(matrix), len(matrix[0])
if r == 0 or c == 0: return 0
self.r, self.c = r, c
res = 0
f = [[-1] * c for i in range(r)]
for i in range(r):
for j in range(c):
# 尝试矩阵中的每一个起点开始的最长递增路径
res = max(res, self.dp(i, j, f, matrix))
return res