最长递减路径节点数查找

45 阅读3分钟

问题描述

小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) 开始的最长递减路径的长度。

算法步骤

  1. 初始化

    • 创建一个与网格大小相同的二维数组 dp,初始值为 0。
    • 定义一个方向数组 directions,表示上下左右四个方向的移动。
  2. DFS 函数

    • 对于每个节点 (x, y),如果 dp[x][y] 已经计算过(即不为 0),则直接返回 dp[x][y]

    • 否则,初始化 dp[x][y] 为 1(表示当前节点本身)。

    • 遍历四个方向,计算每个方向上的新位置 (nx, ny)

      • 检查新位置是否在网格内且值严格小于当前值 grid[x][y]
      • 递归计算新位置的最长路径长度,并更新当前节点的最长路径长度。
  3. 遍历网格

    • 对于每个节点 (i, j),调用 DFS 函数计算其最长递减路径长度,并更新全局最长路径长度。
  4. 返回结果

    • 返回全局最长路径长度。

代码实现: 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)