AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

LeetCode 329. Longest Increasing Path in a Matrix    原题链接    困难

作者: 作者的头像   yxc ,  2018-06-27 22:05:52 ,  所有人可见 ,  阅读 2994


10


6

题目描述

给定一个整数矩阵,请找到最长的上升路径。

对于矩阵中的每个格子,你每次可以走到上下左右四个方向,不能斜着走,也不能走出边界。

样例1

输入:nums = 
[
  [9,9,4],
  [6,6,8],
  [2,1,1]
] 
输出:4 
解释:最长的上升路径是:[1, 2, 6, 9].

样例2

输入:nums = 
[
  [3,4,5],
  [3,2,6],
  [2,2,1]
] 
输出:4 
解释:最长的上升路径是:[3, 4, 5, 6]. 不能斜着走。

算法

(记忆化搜索,动态规划) $O(n^2)$

这是动态规划里非常经典的一道题目,几乎是所有学编程的同学都会遇到的一道题目。

假设我们从最低点开始走,每次只能往更高的格子走。
状态表示:f[i][j]表示走到(i,j)这个格子时的最大长度。
状态转移:枚举上下左右四个格子,如果某个格子(a,b)比当前格子低,则用该格子更新当前格子的最大长度:f[i][j] = max(f[i][j], dp(a, b) + 1)。

由于这道题目的状态依赖关系比较复杂,不容易用循环来求每个状态的值,所以可以用记忆化搜索来做:如果某个状态还没计算过,则递归计算该状态的值。

时间复杂度分析:假设矩阵的边长是 $n$。则总共有 $n^2$ 个状态,状态转移的计算量是常数,所以总时间复杂度是 $O(n^2)$。

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;
    }
};

9 评论


用户头像
zml24   2021-04-15 16:31         踩      回复

这道题是不是也可以用差分约束呀 求最长路


用户头像
普朗tong   2020-08-20 23:54         踩      回复

寻找最长递增路径,不应该是比较g[a][b]>g[x][y]吗,为什么这里比较g[a][b]<g[x][y]了?

用户头像
yxc   2020-09-22 14:07         踩      回复

两种定义方式都是可以的。要不定义成从起点走到(x, y)的最大长度,要不定义成从(x, y)走到终点的最大长度。


用户头像
贺谦   2020-07-26 22:34         踩      回复

y总,什么是记忆化搜索?在代码中是怎么样体现的?

用户头像
yxc   2020-08-18 12:31      1    踩      回复

就是暴搜的时候加个数组存结果。


用户头像
小雨   2018-09-10 09:40         踩      回复

题真的是要多做几遍好,第二次或者第三次做的时候,感觉想得会深入一些些,有一种常做常新的感觉。 这道题, 刚开始算某一个 cell longest increasing path 的时候会比较慢,因为在算第一个的时候,要把周围的都算一遍,后面会算得比较快,但我还是不太明白,为什么这样反复算就可以呢?

用户头像
yxc   2018-09-10 11:57         踩      回复

这道题目要从整体去考虑,由于不会重复计算状态,状态总共有 $n^2$ 个,计算每个状态需要常数时间,所以总时间复杂度是 $O(n^2)$。
由于每个点只能从比它小的点转移,所以状态之间不会产生循环依赖关系,所以每个状态都可以通过有限次递归算出来。

用户头像
小雨   2018-09-10 22:56    回复了 yxc 的评论         踩      回复

不会产生循环依赖关系, 是说不会有loop 的意思是么,只要 matrix是有限大的,总是可以递归走完的。

用户头像
yxc   2018-09-10 22:58    回复了 小雨 的评论         踩      回复

对滴!所以每个状态都可以被计算出来。


App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息