矩阵中的最长递增路径

329. 矩阵中的最长递增路径

给定一个 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

思路:

  这道题好像是个困难题,但根据题意你会发现,题目给出的具体最长路径只是用来解释说明用的,并不需要我们真正输出具体的最长路径,只需要一个数字而已。因此我们在思考的时候就不需要去纠结怎么把路径保留、通过已有路径去探索之类的操作了 。

  这道题得借鉴动态规划的思路去做。与常规动态规划不同的是,这道题的dp数组并不是一个真正的数组,而是一个字典。我们不再调用dp[i][j],而是调用dp[(i,j)],除了形式上稍有不同之外,我们依然使用类似标准动态规划的方式去状态转移

  具体思路为:我们定义字典memo,memo[(i,j)]表示以(i,j)位置为终点的路径最大长度。我们知道,(i,j)位置可以来自它的上下左右(如果没越界),因此状态转移方程就可以写成:memo[(i,j)] = maxmemo[(i,j)位置的上下左右]+1

  知道了这个动态规划的基本思路后,我们还需要一个递归函数recur()来帮我们进行实现。这个递归函数的作用就是:传入位置(i,j),通过状态转移算出对应的memo[(i,j)]值后,把这个键值对添加进memo字典并返回这个值。即每一个位置经过recur函数之后,都可以得到以它结尾的路径的最大长度。函数会将这个值存入memo字典,并返回这个值。

  最终,我们的整个memo字典其实就相当于是一个二维dp数组,里面对应以每一个位置为终点时路径的最大值,我们拿出最大值即可,完全不用关心具体路径是什么。

代码:

class Solution(object):
    def longestIncreasingPath(self, matrix):
        m, n = len(matrix), len(matrix[0])
        memo = {}#记忆字典
        #memo[(i,j)]表示以(i,j)位置为终点的路径最大长度
        def recur(i, j):#函数功能:计算、添加memo[(i,j)]并返回值
            if (i, j) in memo:#如果这个点计算过了,直接返回
                return memo[(i, j)]
            #都初始化为0 这个是base case
            temp1, temp2, temp3, temp4 = 0, 0, 0, 0         
            #base case结束
            #向下没越界 并且可以从下面上来
            if i+1<=m-1 and matrix[i][j]>matrix[i+1][j]:
                temp1 = recur(i+1, j)
            #向右 并且可以从右边过来
            if j+1<=n-1 and matrix[i][j]>matrix[i][j+1]:
                temp2 = recur(i, j+1)
            if i-1>=0 and matrix[i][j]>matrix[i-1][j]:#向上 同理
                temp3 = recur(i-1, j)
            if j-1>=0 and matrix[i][j]>matrix[i][j-1]:#向左 同理
                temp4 = recur(i, j-1)   
            memo[(i, j)] = max(temp1, temp2, temp3, temp4)+1#在4个方向中找到最大的
            return memo[(i, j)]
        for x in range(m):#对每一个位置都进行一遍这个操作
            for y in range(n):
                recur(x, y)
        return max(memo.values())#最后只需在记忆字典中找到最大的值

  这个解法是利用了“记忆字典”(也叫备忘录)来帮助状态存储和状态转移。我们的状态转移看似只考虑了相邻的上下左右四个位置,但因为递归的存在,程序会自行的考虑(递归)到全盘。

posted @   JunanP  阅读(19)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示