一.题目
329. 矩阵中的最长递增路径 - 力扣(LeetCode)

二.思路讲解
2.1 思路讲解
本题要求矩阵中最长递增路径的长度。我们可以采用暴力枚举起点 + 深度优先搜索的思路:从矩阵的每个格子出发,向上下左右四个方向探索,只允许走向值更大的格子,并统计该路径的长度。
但直接递归会导致大量重复计算,因此引入记忆化搜索 :用一个备忘录数组 memo 记录每个格子已经计算出的最长递增路径长度,在递归前先查表,若已计算则直接返回,否则递归计算后存入备忘录。这样每个格子只计算一次。通过这种"暴力枚举 + 记忆化"的优化,就能高效求出整个矩阵的最长递增路径长度。
三.代码演示
cpp
class Solution {
public:
int row,col;
int bx[4] = {0,0,1,-1};
int by[4] = {1,-1,0,0};
int memo[201][201];
int longestIncreasingPath(vector<vector<int>>& matrix)
{
row = matrix.size(),col = matrix[0].size();
int ret = 0;
for(int i = 0;i < row;i++)
{
for(int j = 0;j < col;j++)
{
ret = max(ret,dfs(matrix,i,j));
}
}
return ret;
}
int dfs(vector<vector<int>>& matrix,int i,int j)
{
if(memo[i][j] != 0) return memo[i][j];
int path = 1;//包括自己
for(int k = 0;k < 4;k++)
{
int x = i + bx[k],y = j + by[k];
if(x >= 0 && y >= 0 && x < row && y < col && matrix[x][y] > matrix[i][j])
{
path = max(path,dfs(matrix,x,y) + 1);
}
}
memo[i][j] = path;
return path;
}
};
四.代码讲解
一、全局变量与数据结构
-
row、col:成员变量,存储矩阵的行数和列数。 -
方向数组
bx[4]、by[4]:表示上下左右四个方向的偏移量,用于探索相邻格子。 -
memo[201][201]:二维数组,作为备忘录,memo[i][j]表示从格子(i, j)出发的最长递增路径长度,初始为0(表示未计算)。
二、主函数 longestIncreasingPath
-
获取矩阵尺寸
row和col。 -
初始化结果变量
ret = 0。 -
遍历所有格子,对每个格子
(i, j)调用dfs(matrix, i, j)计算以该格子为起点的最长递增路径长度,并更新ret为最大值。 -
返回
ret。
三、递归函数 dfs
dfs(matrix, i, j) 返回从格子 (i, j) 出发的最长递增路径长度。执行流程如下:
1. 查备忘录
如果 memo[i][j] != 0,说明该子问题已经计算过,直接返回存储的值。这是记忆化搜索的核心优化,避免重复计算。
2. 初始化当前路径长度
将 path 初始化为 1,因为至少包含当前格子本身。
3. 向四个方向探索
遍历四个方向,计算新坐标 (x, y):
-
边界检查 :
x >= 0 && y >= 0 && x < row && y < col -
递增条件 :
matrix[x][y] > matrix[i][j]若满足,则递归调用dfs(matrix, x, y)得到以(x, y)为起点的最长递增路径长度,加上当前格子后长度即为dfs(matrix, x, y) + 1。用max更新path。
4. 存入备忘录并返回
将计算得到的 path 存入 memo[i][j],然后返回 path。
四、关键细节
-
记忆化:每个格子只计算一次。
-
递归方向:由于只能走向值更大的格子,不存在循环依赖,递归能正确终止。
-
备忘录初始值 :用
0表示未计算,因为路径长度至少为 1,不会与有效值冲突。
五、流程图
