题目介绍
力扣329题:leetcode-cn.com/problems/lo…
深度搜索
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。