最长递减路径节点数查找问题
本篇文章探讨了在一个二维整数网格中寻找最长递减路径的问题。小C希望找到一条路径,使得路径上的每个节点值都严格递减,并且只能上下左右移动。通过动态规划结合深度优先搜索(DFS)的方式,我们定义了状态并利用记忆化优化了计算过程,以有效找出从任意节点出发的最长递减路径的长度。最后,通过遍历整个网格,计算出最长递减路径的节点数量。
一、问题描述
小C正在研究一个二维整数网格Grid,他的目标是找到一条包含最多节点的路径,这条路径上每个节点的值都必须严格递减。小C只能在网格内上下左右移动,不能走对角线,也不能走出网格的边界。
小C想知道,经过这种规则能找到的最长递减路径的节点个数是多少。
例如,给定一个网格:
9 6 4
5 6 7
2 1 1
最长的递减路径是 [7, 6, 5, 2, 1],这条路径的节点数为5。
二、解题思路
为了找到最长的递减路径,我们可以使用动态规划和深度优先搜索的结合方法。主要思路如下:
- 定义状态:我们使用一个二维数组
dp来存储从每个节点开始的最长递减路径的长度。 - DFS与记忆化:使用 DFS 遍历每个节点,并根据其相邻节点的值来递归计算最长递减路径。在递归过程中,利用
dp数组进行记忆化,以避免重复计算。 - 边界条件:在 DFS 时,只能向上下左右相邻的节点移动,且当前节点的值必须大于相邻节点的值才能形成递减路径。
- 结果更新:通过对所有节点调用 DFS 函数,更新并记录得到的最大路径长度。
三、解题步骤
-
初始化:
- 创建一个存储网格行数和列数的变量。
- 初始化一个
dp数组,用于存储每个节点的最长递减路径长度。
-
定义 DFS 函数:
- 在 DFS 函数中,检查当前节点是否已经计算过。如果已经计算,则直接返回该节点的最长路径长度。
- 否则,遍历当前节点的四个方向的邻接节点,检查它们的值是否小于当前节点的值,如果是,则递归调用 DFS。
-
遍历所有节点:
- 对网格中的每个节点调用 DFS 函数,更新最长路径的结果。
-
输出结果:
- 返回最终找到的最长递减路径的节点数。
四、代码实现
以下是使用Go实现的代码:
func longestDecreasingPath(grid [][]int) int {
if len(grid) == 0 || len(grid[0]) == 0 {
return 0
}
rows := len(grid)
cols := len(grid[0])
dp := make([][]int, rows) // 用于存储每个节点的最长递减路径长度
for i := range dp {
dp[i] = make([]int, cols)
}
var dfs func(x, y int) int
dfs = func(x, y int) int {
if dp[x][y] != 0 { // 如果已经计算过,直接返回
return dp[x][y]
}
maxLength := 1 // 当前节点至少包含自己
// 定义方向数组:上下左右
directions := [][2]int{
{1, 0}, // 下
{-1, 0}, // 上
{0, 1}, // 右
{0, -1}, // 左
}
for _, direction := range directions {
nx, ny := x+direction[0], y+direction[1] // 计算相邻节点坐标
if nx >= 0 && nx < rows && ny >= 0 && ny < cols && grid[nx][ny] < grid[x][y] {
maxLength = max(maxLength, 1+dfs(nx, ny)) // 更新最大长度
}
}
dp[x][y] = maxLength // 存储结果
return maxLength
}
result := 0
for i := 0; i < rows; i++ {
for j := 0; j < cols; j++ {
result = max(result, dfs(i, j)) // 更新全局最大值
}
}
return result
}
// 辅助函数:获取较大值
func max(a, b int) int {
if a > b {
return a
}
return b
}
五、复杂度分析
- 时间复杂度:O(m * n),其中 m 和 n 分别是网格的行数和列数。每个节点最多被访问一次,因此总的复杂度是 O(m * n)。
- 空间复杂度:O(m * n),用于存储 DP 数组和递归栈空间。
六、总结
在解决最长递减路径的问题时,利用 DFS 与动态规划的组合,有效地找到符合条件路径长度。通过记忆化存储中间结果,可以显著提高算法效率。这种方法不仅适用于本问题,还可以扩展到其他图形遍历相关的问题中。