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

133 阅读2分钟

题目介绍

力扣329题:leetcode-cn.com/problems/lo…

image.png

image.png

深度搜索

matrix 为储存原本数字的矩阵,创建一个新矩阵 memo,每一个格子 (i,j) 表示在 matrix 上走到格子 (i,j),最长的递增路径长度   旁白:每次当我们看到一个新格子,我们问什么问题?   小明问:我能从哪里走到这个格子?

小红答:上、下、左、右四个格子中,matrix 中储存的数字小于我这个格子的地方,都可以走到我现在这个格子   小明问:那我在能选的选项里选哪个?

小红答:选上、下、左、右中 memo值 最大的   小明问:那我现在这个格子的 memo值 应该存多少?

小红答:就是我选择的上一个格子储存的 memo值 +1 呗   小明问:那我怎么算上、下、左、右每个格子储存了多长的路径?

小红答:重复上面相同的搜索方式(查看这些格子各自的上下左右),直到我遇到一个格子,这个格子上下左右比它 matrix值 小的格子的 memo值 都已知了   小明问:可是我没有初始化我的 memo 矩阵,怎么可能一开始就深搜到一个周围 memo值 都已知的格子呢?

小红说:当你搜到一个格子,这个格子里的 matrix 数字很小,上下左右格子都比它大,你说我现在这个格子的 memo值 的计算,还需要看上下左右的 memo值 吗?这个格子的 memo值 直接填1就可以啦   小红补充说:从某个格子开始的深搜,不能保证整个 matrix 都被覆盖,所以你每次 matrix 里遇到一个还没有 memo值 的格子,就从它开始往底下深搜就行啦。

小明说:啦啦啦啦啦啦

代码如下:

class Solution {
    public int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    public int rows, columns;

    public int longestIncreasingPath(int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return 0;
        }
        rows = matrix.length;
        columns = matrix[0].length;
        int[][] memo = new int[rows][columns];
        int ans = 0;
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < columns; ++j) {
                ans = Math.max(ans, dfs(matrix, i, j, memo));
            }
        }
        return ans;
    }

    //深度搜索
    public int dfs(int[][] matrix, int row, int column, int[][] memo) {
        if (memo[row][column] != 0) {
            return memo[row][column];
        }
        memo[row][column]++;
        for (int[] dir : dirs) {
            int newRow = row + dir[0], newColumn = column + dir[1];
            if (newRow >= 0 && newRow < rows && newColumn >= 0 && newColumn < columns && matrix[newRow][newColumn] > matrix[row][column]) {
                memo[row][column] = Math.max(memo[row][column], dfs(matrix, newRow, newColumn, memo) + 1);
            }
        }
        return memo[row][column];
    }
}

复杂度分析

  • 时间复杂度:O(mn),其中 m 和 n 分别是矩阵的行数和列数。深度优先搜索的时间复杂度是 O(V+E),其中 V 是节点数,E 是边数。在矩阵中,O(V)=O(mn) O(E)≈O(4mn)=O(mn)。

  • 空间复杂度:O(mn) ,其中 m 和 n 分别是矩阵的行数和列数。空间复杂度主要取决于缓存和递归调用深度,缓存的空间复杂度是 O(mn) ,递归调用深度不会超过 mn。