问题描述
小C正在研究一个二维整数网格Grid,他的目标是找到一条包含最多节点的路径,这条路径上每个节点的值都必须严格递减。小C只能在网格内上下左右移动,不能走对角线,也不能走出网格的边界。
小C想知道,经过这种规则能找到的最长递减路径的节点个数是多少。
例如,给定一个网格:
9 6 4
5 6 7
2 1 1
最长的递减路径是 [7, 6, 5, 2, 1],这条路径的节点数为5。
解题思路:
- 我们需要在一个二维网格中找到一条路径,这条路径上的每个节点的值都必须严格递减。
- 路径可以从任意节点开始,并且可以在网格内上下左右移动,但不能走对角线或走出网格边界。
数据结构选择
- 使用一个二维数组
dp来存储每个节点的最长递减路径长度。dp[i][j]表示从节点(i, j)开始的最长递减路径的长度。
算法步骤
-
初始化:
- 创建一个与网格大小相同的二维数组
dp,初始值为 0。 - 定义一个方向数组
directions,表示上下左右四个方向的移动。
- 创建一个与网格大小相同的二维数组
-
DFS 函数:
-
对于每个节点
(x, y),如果dp[x][y]已经计算过(即不为 0),则直接返回dp[x][y]。 -
否则,初始化
dp[x][y]为 1(表示当前节点本身)。 -
遍历四个方向,计算每个方向上的新位置
(nx, ny):- 检查新位置是否在网格内且值严格小于当前值
grid[x][y]。 - 递归计算新位置的最长路径长度,并更新当前节点的最长路径长度。
- 检查新位置是否在网格内且值严格小于当前值
-
-
遍历网格:
- 对于每个节点
(i, j),调用 DFS 函数计算其最长递减路径长度,并更新全局最长路径长度。
- 对于每个节点
-
返回结果:
- 返回全局最长路径长度。
代码实现: def solution(R: int, C: int, grid: list) -> int: # 定义方向数组,分别表示上、下、左、右四个方向 directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
# 初始化 dp 数组,用于存储每个节点的最长递减路径长度
dp = [[0] * C for _ in range(R)]
def dfs(x, y):
# 如果 dp[x][y] 已经计算过,直接返回
if dp[x][y] != 0:
return dp[x][y]
# 初始化当前节点的最长路径长度为 1
dp[x][y] = 1
# 遍历四个方向
for dx, dy in directions:
nx, ny = x + dx, y + dy
# 检查新位置是否在网格内且值严格小于当前值
if 0 <= nx < R and 0 <= ny < C and grid[nx][ny] < grid[x][y]:
# 递归计算新位置的最长路径长度,并更新当前节点的最长路径长度
dp[x][y] = max(dp[x][y], dfs(nx, ny) + 1)
return dp[x][y]
# 初始化最长路径长度为 0
max_length = 0
# 遍历整个网格,计算每个节点的最长路径长度,并更新全局最长路径长度
for i in range(R):
for j in range(C):
max_length = max(max_length, dfs(i, j))
return max_length
if name == 'main': print(solution(3, 3, [[9, 6, 4], [5, 6, 7], [2, 1, 1]]) == 5) print(solution(4, 4, [[10, 9, 8, 7], [6, 5, 4, 3], [7, 6, 5, 4], [8, 7, 6, 5]]) == 6) print(solution(2, 2, [[-1, -2], [-3, -4]]) == 3)