Q:给定一个整数矩阵,找出最长递增路径的长度。对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。
示例 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]。注意不允许在对角线方向上移动。
A:
1.记忆化深度优先搜索:从一个单元格开始进行深度优先搜索,即可找到从该单元格开始的最长递增路径。对每个单元格分别进行深度优先搜索之后,即可得到矩阵中的最长递增路径的长度。使用记忆化深度优先搜索,当访问到一个单元格 ((i,j)) 时,如果 (visited[i,j]
eq-1),说明该单元格的结果已经计算过,则直接从缓存中读取结果,如果 (visited[i,j]=-1),说明该单元格的结果尚未被计算过,则进行搜索,并将计算得到的结果存入缓存中。遍历完矩阵中的所有单元格之后,即可得到矩阵中的最长递增路径的长度。
private int[] visited;
private int[] idx = new int[]{-1, 0, 1, 0, -1};
public int longestIncreasingPath(int[][] matrix) {
if (matrix.length == 0)
return 0;
int m = matrix.length;//行数
int n = matrix[0].length;//列数
visited = new int[m * n];
if (visited.length == 1)
return 1;
Arrays.fill(visited, -1);
int max = Integer.MIN_VALUE;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (visited[i * n + j] == -1) {
int result = longestPathLength(matrix, i, j);
max = Math.max(max, result);
} else {
max = Math.max(max, visited[i * n + j]);
}
}
}
return max;
}
private int longestPathLength(int[][] matrix, int i, int j) {
int m = matrix.length;//行数
int n = matrix[0].length;//列数
int max = 1;
for (int k = 0; k < 4; k++) {
int newx = i + idx[k];
int newy = j + idx[k + 1];
if (newx >= 0 && newy >= 0 && newx < matrix.length && newy < matrix[0].length) {
int curr = visited[newx * n + newy];
if(matrix[newx][newy] > matrix[i][j]){
if (curr == -1) {
max = Math.max(max, longestPathLength(matrix, newx, newy) + 1);
} else {
max = Math.max(max, curr + 1);
}
}
}
}
visited[i * n + j] = max;
return max;
}
2.拓扑排序
private int[][] count;
private int[] idx = new int[]{-1, 0, 1, 0, -1};
public int longestIncreasingPath(int[][] matrix) {
if (matrix.length == 0)
return 0;
int m = matrix.length;
int n = matrix[0].length;
count = new int[m][n];
for (int i = 0; i < m; i++) {
Arrays.fill(count[i], 0);
}
//小数指向大数
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < 4; k++) {
int newx = i + idx[k];
int newy = j + idx[k + 1];
if (newx >= 0 && newy >= 0 && newx < m && newy < n && matrix[newx][newy] < matrix[i][j])
count[i][j]++;
}
}
}
Queue<int[]> q = new LinkedList<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (count[i][j] == 0)
q.add(new int[]{i, j});
}
}
int ans = 0;
//一层一层来,直到找到最长的路径
while (!q.isEmpty()) {
ans++;
int size = q.size();
for (int i = 0; i < size; i++) {
int[] poll = q.poll();
int x = poll[0];
int y = poll[1];
for (int k = 0; k < 4; k++) {
int newx = x + idx[k];
int newy = y + idx[k + 1];
if (newx >= 0 && newy >= 0 && newx < m && newy < n && matrix[newx][newy] > matrix[x][y]) {
if (--count[newx][newy] == 0) {
q.add(new int[]{newx, newy});
}
}
}
}
}
return ans;
}