矩阵中的最长递增路径
难度:
标签:
题目描述
English description is not available for the problem. Please switch to Chinese.
代码结果
运行时间: 116 ms, 内存: 17.0 MB
/*
* 思路:
* 1. 我们依旧定义一个方向数组dirs,表示四个可能的方向。
* 2. 使用一个记忆化的二维数组dp,其中dp[i][j]表示以matrix[i][j]为起点的最长递增路径的长度。
* 3. 对于每个单元格(i, j),使用深度优先搜索(DFS)来找到以它为起点的最长递增路径。
* 4. 在DFS过程中,如果移动后的值大于当前值,递归计算移动后的单元格的最长递增路径长度,并更新dp[i][j]。
* 5. 最后遍历dp数组,找到最大的值即为答案。
*/
import java.util.Arrays;
import java.util.stream.IntStream;
public class Solution {
private static final int[][] dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
private int m, n;
public int longestIncreasingPath(int[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
m = matrix.length;
n = matrix[0].length;
int[][] dp = new int[m][n];
return IntStream.range(0, m)
.flatMap(i -> IntStream.range(0, n)
.map(j -> dfs(matrix, i, j, dp)))
.max()
.orElse(0);
}
private int dfs(int[][] matrix, int i, int j, int[][] dp) {
if (dp[i][j] != 0) {
return dp[i][j];
}
int max = 1;
for (int[] dir : dirs) {
int x = i + dir[0], y = j + dir[1];
if (x >= 0 && x < m && y >= 0 && y < n && matrix[x][y] > matrix[i][j]) {
max = Math.max(max, 1 + dfs(matrix, x, y, dp));
}
}
dp[i][j] = max;
return max;
}
}
解释
方法:
该题解采用了拓扑排序的思想,将矩阵中的每个单元格视为图中的一个节点,如果一个单元格的值小于它相邻的单元格,则在这两个单元格之间存在一条有向边。因此,该问题转化为了找出这个有向图中的最长路径。首先,我们计算每个单元格的出度(即有多少条边从该单元格指向其他单元格),并将出度为0的单元格(即没有任何边指向其他单元格的单元格)加入队列中。然后,我们开始进行拓扑排序,每次从队列中取出一个单元格,并将其相邻单元格的出度减1,如果某个相邻单元格的出度变为0,则将其加入队列中。每次从队列中取出单元格时,路径长度加1。重复这个过程,直到队列为空,此时的路径长度即为最长递增路径的长度。
时间复杂度:
O(mn)
空间复杂度:
O(mn)
代码细节讲解
🦆
在实现拓扑排序时,您是如何处理矩阵边界的?例如,如果一个单元格位于矩阵的边缘,您会如何确保不会检查超出矩阵边界的单元格?
▷🦆
题解中提到了将出度为0的单元格加入队列,能否解释为什么选择出度为0的单元格开始而非入度为0的单元格?
▷🦆
在拓扑排序的过程中,您是如何保证每次从队列中取出单元格时路径长度都正确增加的?特别是在多个单元格同时出队时。
▷