329. 矩阵中的最长递增路径
给定一个整数矩阵,找出最长递增路径的长度。
对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。
解题思路: 虽然此题标记的难度是难,但是设计好了图遍历的函数形式,解此题不太难,之前做题,尤其是做与路径统计的极值问题时,会发现设计一个号的函数形式,具体的说,是函数的形参和返回值的物理涵义,会非常有利于打开解题的思路。题目要求的是醉成递增路径,那么我们先分析一下,所有的路径一定是以图中某个点为起点,然后向四周延展,那么我们可以遍历每一个点,以这个点为起点,记录这个路径最长能达到多长,即可遍历完图中所有的路径,然后需要解决的是如何求以这个节点出发的最长路径,路径的延展无非是向四个方向进行,那么我在判定当前这个节点最长路径时,只需要前确定与这个节点相邻的四个节点中最长路径即可,然后这个最长路径加1即为当前节点出发的最长路径,OK,至此,此题的思路应该就比较明晰了,函数的返回值肯定是设计为当前节点的最长路径值。由于图的遍历是近乎暴力解法,对其中一个节点遍历时,又会把四周节点的路径值重复求一遍,这个会存在大量的重复计算,因此可以借助记忆数组,避免重复计算。好了,我们可以看一下此题的解题代码。
// 标签:图的遍历+记忆数组
// 本题本质上是在考察图的遍历,由于图的遍历近乎暴力解法,但是此题
// 的遍历情形中存在大量重复的计算,因此可以用记忆数组保存已经遍历
// 的结果,以减少时间复杂度.
// Space: O(n),时间复杂度有点不好分析,暂不分析了
class Solution {
public:
int helper(vector<vector<int>>& matrix, int r, int c) {
if (m.count({r,c})) return m[{r,c}];
int mx = 0;
int rows = matrix.size(), cols = matrix[0].size();
for (auto dir : dirs) {
int x = r + dir[0], y = c + dir[1];
if (x < 0 || x >= rows || y < 0 || y >= cols) continue;
if (matrix[x][y] > matrix[r][c]) {
mx = max(mx, helper(matrix, x, y));
}
}
return m[{r,c}] = mx + 1;
}
int longestIncreasingPath(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return 0;
int rows = matrix.size(), cols = matrix[0].size();
int res = 0;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
res = max(res, helper(matrix, i, j));
}
}
return res;
}
private:
map<pair<int, int>, int> m;
vector<vector<int>> dirs = {{1,0},{-1,0},{0,1},{0,-1}};
};