LeetCode 329. Longest Increasing Path in a Matrix
给定一个 m x n 整数矩阵 matrix ,找出其中 最长递增路径 的长度。
对于每个单元格,你可以往上,下,左,右四个方向移动。 你 不能 在 对角线 方向上移动或移动到 边界外(即不允许环绕)。
示例 1:
输入: matrix = [[9,9,4],[6,6,8],[2,1,1]]
输出: 4
解释: 最长递增路径为 [1, 2, 6, 9]。
示例 2:
输入: matrix = [[3,4,5],[3,2,6],[2,2,1]]
输出: 4
解释: 最长递增路径是 [3, 4, 5, 6]。注意不允许在对角线方向上移动。
示例 3:
输入: matrix = [[1]]
输出: 1
提示:
m == matrix.lengthn == matrix[i].length1 <= m, n <= 2000 <= matrix[i][j] <= 231 - 1
算法
(记忆化搜索,动态规划) O()
这是动态规划里非常经典的一道题目,几乎是所有学编程的同学都会遇到的一道题目。
假设我们从最低点开始走,每次只能往更高的格子走。
状态表示:f[i][j]表示走到(i,j)这个格子时的最大长度。
状态转移:枚举上下左右四个格子,如果某个格子(a,b)比当前格子低,则用该格子更新当前格子的最大长度:f[i][j] = max(f[i][j], dp(a, b) + 1)。
由于这道题目的状态依赖关系比较复杂,不容易用循环来求每个状态的值,所以可以用记忆化搜索来做:如果某个状态还没计算过,则递归计算该状态的值。
时间复杂度分析
假设矩阵的边长是 n。则总共有 个状态,状态转移的计算量是常数,所以总时间复杂度是 O()。
C++ 代码
class Solution {
public:
int n, m;
vector<vector<int>> f, g;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int dp(int x, int y)
{
if (f[x][y] != -1) return f[x][y];
f[x][y] = 1;
for (int i = 0; i < 4; i ++ )
{
int a = x + dx[i], b = y + dy[i];
if (a >= 0 && a < n && b >= 0 && b < m && g[a][b] < g[x][y])
f[x][y] = max(f[x][y], dp(a, b) + 1);
}
return f[x][y];
}
int longestIncreasingPath(vector<vector<int>>& matrix) {
if (matrix.empty()) return 0;
g = matrix;
n = g.size(), m = g[0].size();
f = vector<vector<int>>(n, vector<int>(m, -1));
int res = 0;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
res = max(res, dp(i, j));
return res;
}
};