矩阵中的最长递增路径

一、前言

问题来源LeetCode 329,难度:困难

问题链接:https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix

 

二、题目

给定一个整数矩阵,找出最长递增路径的长度。对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。

示例 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]。注意不允许在对角线方向上移动。

 

三、思路

三种解法

3.1 方法一:朴素的深度优先搜索

时间复杂度:O(2^(m+n)),空间复杂度:O(mn)

3.2 方法二:带备忘录的深度优先搜索

时间复杂度:O(mn),空间复杂度:O(mn)

3.3 方法三:拓扑排序+记忆化搜索

时间复杂度:O(mn),空间复杂度:O(mn)

拓扑排序步骤:

  • 从DGA图中找到一个没有前驱的顶点输出。(可以遍历,也可以用优先队列维护)
  • 删除以这个点为起点的边。(它的指向的边删除,为了找到下个没有前驱的顶点)
  • 重复上述,直到最后一个顶点被输出。如果还有顶点未被输出,则说明有环!

输出并删除没有前驱的顶点,一直重复这个过程。对应本题中整数矩阵,没有前驱的顶点就是最小的数,找到最小的数就可以确定它上下左右位置上的数最长路径。

拓扑排序原理可以参考:https://www.cnblogs.com/bigsai/p/11489260.html

 

四、编码技巧

在判断上下左右坐标的时候,可以定义一个数组保存上下左右移动的坐标增量,这样就可以通过循环来进行坐标点判断。而不用进行四次坐标点判断了。

static const int dirs[4][2] = { {0, 1}, {-1, 0}, {0, -1}, {1, 0} };  // 分别是 向后、向下、向左、向上
for (int i = 0; i < 4; ++i)
{
    int nh = ph + dirs[i][0];
    int nx = px + dirs[i][1];
    if (nh >= 0 && nh <= maxH && nx >= 0 && nx <= maxX && matrix[ph][px] < matrix[nh][nx])
    {
        int ret = longestIncreasingPath(matrix, nh, nx) + 1;
        maxPath = max(maxPath, ret);
    }
}

 

五、编码实现

//==========================================================================
/**
* @file : 329_LongestIncreasingPath.h
* @title: 矩阵中的最长递增路径
* @purpose : 给定一个整数矩阵,找出最长递增路径的长度。对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。
*
* 示例 1:
* 输入: nums =
* [
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值