[leetcode每日一题2020/7/26]329. 矩阵中的最长递增路径

矩阵中的最长递增路径

  • 题目
  • 思路
  • 代码
  • 复杂度分析

题目来源于leetcode,解法和思路仅代表个人观点。传送门。
难度:困难
用时:01:30:00

题目

给定一个整数矩阵,找出最长递增路径的长度。

对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。

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

思路

解法一(深度遍历+记忆优化):

  1. 对每个点进行深度遍历【调用dfs函数】,返回该点的最长递增路径。
  2. 【dfs函数】类似二叉树求深度。对每个点的四个方向进行深度遍历。返回这个方向的长度。
  3. 【dfs函数】比较四个方向的长度,返回最大的长度,并+1。

如果只是进行深度遍历的话,会超时。所以需要使用数组记录一些东西。
仔细分析就会发现,每个点的最长递增路径是固定的。所以,可以使用一个相同大小的数组,保存每个点的最长递增路径。当访问该点时,如果数组值不为0,就返回当前点的数组值。

代码

class Solution {
    //上下左右
    int[][] direction = {{0,1},{0,-1},{-1,0},{1,0}};
    public int longestIncreasingPath(int[][] matrix) {
    	//空数组时
        if (matrix.length == 0) return 0;

        //标记当前点的最长递增路径
        int[][] mark = new int[matrix.length][matrix[0].length];

        int maxAscentLength=0;
        //遍历每一个节点,对其进行dfs
        for(int i=0;i<matrix.length;i++){
            for(int j=0;j<matrix[0].length;j++){
                int length = dfs(i,j,matrix,mark);
                if(maxAscentLength<length){
                    maxAscentLength = length;
                }
            }
        }
        return maxAscentLength;
    }

	//深度遍历
    private int dfs(int i,int j,int[][] matrix,int[][] mark){
        int up = 0;
        int down = 0;
        int left = 0;
        int right = 0;

        //返回当前点的最长路径
        if(mark[i][j] != 0){
            return mark[i][j];
        }

        //遍历四个方向
        //不走这个方向的条件
        //1.到边界尽头
        //2.找不到递增路径

        //上
        int row = i+direction[0][0];
        int col = j+direction[0][1];
        if(row>=0&&row<matrix.length){
            if(col>=0&&col<matrix[0].length){
                if(matrix[i][j]<=matrix[row][col]){
                    up = 0;
                }else{
                    up = dfs(row,col,matrix,mark);
                }
            }
        }
        
        //下
        row = i+direction[1][0];
        col = j+direction[1][1];
        if(row>=0&&row<matrix.length){
            if(col>=0&&col<matrix[0].length){
                if(matrix[i][j]<=matrix[row][col]){
                    down = 0;
                }else{
                    down = dfs(row,col,matrix,mark);
                }
            }
        }

        //左
        row = i+direction[2][0];
        col = j+direction[2][1];
        if(row>=0&&row<matrix.length){
            if(col>=0&&col<matrix[0].length){
                if(matrix[i][j]<=matrix[row][col]){
                    left = 0;
                }else{
                    left = dfs(row,col,matrix,mark);
                }
            }
        }

        //右
        row = i+direction[3][0];
        col = j+direction[3][1];
        if(row>=0&&row<matrix.length){
            if(col>=0&&col<matrix[0].length){
                if(matrix[i][j]<=matrix[row][col]){
                    right = 0;
                }else{
                    right = dfs(row,col,matrix,mark);
                }
            }
        }

		//四个方向中,最长的递增长度
        int maxLength = Math.max(Math.max(up,down),Math.max(left,right));

        //更新mark数组(该点的最长长度)
        mark[i][j] = maxLength;

        return maxLength+1;
    }
}

复杂度分析

时间复杂度:O(mn),其中 mm 和 nn 分别是矩阵的行数和列数。 深度优先搜索的时间复杂度是 O(V+E),其中 V是节点数,E 是边数。
空间复杂度:O(mn),其中 mm 和 nn 分别是矩阵的行数和列数。 缓存空间复杂度是O(mn), 递归调用深度不会超过mn。

你可能感兴趣的:(算法)