Leetcode 329. 矩阵中最长上升路径

题目

给一个矩阵,找到它最长上升路径的长度。对于每一个点,它可以上下左右移动,但是不能斜对角移动。
Example:

Input: nums = 
[
  [9,9,4],
  [6,6,8],
  [2,1,1]
] 
Output: 4 
Explanation: The longest increasing path is [1, 2, 6, 9].

解题思路

最直观的方法是,以矩阵中的每一个点作为起点,对每一个点用dfs搜索,然后求取最大值。直接上代码

class Solution:
    def __init__(self):
        self.ans = 0
    def dfs(self, Matrix, i, j, length):
        self.ans = max(self.ans, length)
        # 开始四个方向 dfs
        if i - 1 >= 0 and Matrix[i][j] < Matrix[i-1][j]:
            self.dfs(Matrix, i-1,j,length + 1)
        if i + 1 < len(Matrix) and Matrix[i][j] < Matrix[i+1][j]:
            self.dfs(Matrix, i+1,j,length + 1)
        if j - 1 >= 0 and Matrix[i][j] < Matrix[i][j-1]:
            self.dfs(Matrix, i,j-1,length + 1)
        if j + 1 < len(Matrix[0]) and Matrix[i][j] < Matrix[i][j+1]:
            self.dfs(Matrix, i,j+1,length + 1)
    def longestIncreasingPath(self, Matrix):
        if len(Matrix)==0:
            return 0
        result = 1
        for i in range(len(Matrix)):
            for j in range(len(Matrix[0])):
                # 以每一个点为起点,起点长度为1,进行dfs.
                self.dfs(Matrix, i, j, 1)
        return self.ans
if __name__=='__main__':
    S = Solution()
    List = [[9,9,4],
            [6,6,8],
            [2,1,1]]
    print(S.longestIncreasingPath(List))

上面的方法,做了很多重复dfs的工作。我们对上面的方法可以进行一个剪枝优化,用记忆化dfs搜索,如果dfs到某一个点,发现该点已经被访问过了,那么就可以直接返回该点为起点的最长路径值,停止往下搜索。比如dfs到点6,我们只需要保存当前点6离终点还有多远,然后保存该值,并且标记为访问过了。如果再次dfs到点6,我们发现如果访问过了,就不用再进行dfs了,只需要返回该点保存的离终点的距离值+1(点6本身)就好了。

# 记忆化优先搜索
class Solution:
    def dfs(self, Matrix, Men, i, j):
        # 初始化为0,如果不为零,说明已经搜索过了
        if Men[i][j] != 0:
            return Men[i][j]
        # 最少为1,包含自己
        Men[i][j] += 1
        # 四个方向进行dfs
        if i - 1 >= 0 and Matrix[i][j] < Matrix[i-1][j]:
            Men[i][j] = max(Men[i][j], self.dfs(Matrix, Men,i-1,j) + 1)
        if i + 1 < len(Matrix) and Matrix[i][j] < Matrix[i+1][j]:
            Men[i][j] = max(Men[i][j], self.dfs(Matrix, Men, i+1, j) + 1)
        if j - 1 >= 0 and Matrix[i][j] < Matrix[i][j-1]:
            Men[i][j] = max(Men[i][j], self.dfs(Matrix, Men, i, j-1) + 1)
        if j + 1 < len(Matrix[0]) and Matrix[i][j] < Matrix[i][j+1]:
            Men[i][j] = max(Men[i][j], self.dfs(Matrix, Men, i, j+1) + 1)
        return Men[i][j]

    def longestIncreasingPath(self, Matrix):
        if len(Matrix)==0:
            return 0
        ans = 1
        ###
        # 初始化访问标记值为0,如果访问标记值为0,则代表未被访问过,继续dfs, 
        # 如果已被访问过,即里面的值大于0(实际上该值代表以该点为起点,最长上升路径长度),
        # 则不必要再对该点进行dfs了.
        ###
        self.Men = [[0 for i in range(len(Matrix[0]))] for j in range(len(Matrix))]
        for i in range(len(Matrix)):
            for j in range(len(Matrix[0])):
                ans = max(ans, self.dfs(Matrix, self.Men, i, j))
        return ans
if __name__=='__main__':
    S = Solution()
    List = [[9,9,4],
            [6,6,8],
            [2,1,1]]
    print(S.longestIncreasingPath(List))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值