Leetcode刷题详解——矩阵中的最长递增路径

1. 题目链接:329. 矩阵中的最长递增路径

2. 题目描述:

给定一个 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.length
  • n == matrix[i].length
  • 1 <= m, n <= 200
  • 0 <= matrix[i][j] <= 231 - 1

算法(记忆化搜索):

算法思路:

  1. 递归含义:给dfs一个使命,给他一个下标[i,j],返回从这个位置开始的最长递增路径的长度

  2. 函数体:上下左右四个方向看一看,哪里能过去就过去,统计四个方向上的最大长度

  3. 递归出口:因为我们是先判断再进入递归,因此没有出口

  4. 用一个备忘录

  5. 每次进入递归的时候,去备忘录里面看看

  6. 每次返回的时候,将结果加入到备忘录里面

算法流程:

  1. 初始化变量mn,分别表示矩阵的行数和列数。
  2. 定义两个数组dx和dy,分别表示四个方向的横坐标变化和纵坐标变化。
  3. 定义一个二维数组memo,用于存储已经计算过的最长递增路径长度。
  4. 遍历矩阵的每一行和每一列,对于每个位置(i, j),调用dfs函数来计算从该位置开始的最长递增路径长度。
  5. dfs函数的作用是从当前位置(i, j)开始,向四个方向进行搜索,找到下一个值大于当前值的位置,然后递归地计算从该位置开始的最长递增路径长度。
  6. 如果已经计算过某个位置的最长递增路径长度,则直接返回该值,避免重复计算。
  7. dfs函数中,使用一个变量ret来记录当前位置的最长递增路径长度,初始值为1
  8. 遍历四个方向,对于每个方向,计算下一个位置的坐标(x, y),如果下一个位置在矩阵范围内且值大于当前位置的值,则递归地计算从该位置开始的最长递增路径长度,并更新ret的值。
  9. 将当前位置的最长递增路径长度存入memo数组,以便后续使用。
  10. 返回当前位置的最长递增路径长度。
  11. longestIncreasingPath函数中,遍历矩阵的每一行和每一列,对于每个位置(i, j),调用dfs函数来计算从该位置开始的最长递增路径长度,并更新ret的值。
  12. 最后,返回ret作为结果,即矩阵中的最长递增路径长度。

请添加图片描述

C++算法代码:

class Solution {
    int m, n; // 定义两个变量m和n,分别表示矩阵的行数和列数
    int dx[4] = {0, 0, 1, -1}; // 定义一个数组dx,表示四个方向的横坐标变化
    int dy[4] = {1, -1, 0, 0}; // 定义一个数组dy,表示四个方向的纵坐标变化
    int memo[201][201]; // 定义一个二维数组memo,用于存储已经计算过的最长递增路径长度

public:
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        int ret = 0; // 初始化最长递增路径长度为0
        m = matrix.size(), n = matrix[0].size(); // 获取矩阵的行数和列数
        for (int i = 0; i < m; i++) { // 遍历矩阵的每一行
            for (int j = 0; j < n; 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 ret = 1; // 初始化当前位置的最长递增路径长度为1
        for (int k = 0; k < 4; k++) { // 遍历四个方向
            int x = i + dx[k], y = j + dy[k]; // 计算下一个位置的坐标
            if (x >= 0 && x < m && y >= 0 && y < n && matrix[x][y] > matrix[i][j]) {
                // 如果下一个位置在矩阵范围内且值大于当前位置的值,则递归计算下一个位置的最长递增路径长度
                ret = max(ret, dfs(matrix, x, y) + 1);
            }
        }
        memo[i][j] = ret; // 将当前位置的最长递增路径长度存入memo数组
        return ret; // 返回当前位置的最长递增路径长度
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值