1.题目描述
给定一个 n 行 m 列矩阵 matrix ,矩阵内所有数均为非负整数。 你需要在矩阵中找到一条最长路径,使这条路径上的元素是递增的。并输出这条最长路径的长度。
这个路径必须满足以下条件:
1. 对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外。
2. 你不能走重复的单元格。即每个格子最多只能走一次。
数据范围:1≤n,m≤10001≤n,m≤1000,0≤matrix[i][j]≤10000≤matrix[i][j]≤1000
进阶:空间复杂度 O(nm)O(nm) ,时间复杂度 O(nm)O(nm)
例如:当输入为[[1,2,3],[4,5,6],[7,8,9]]时,对应的输出为5,
其中的一条最长递增路径如下图所示:
示例1
输入:
[[1,2,3],[4,5,6],[7,8,9]]返回值:
5说明:
1->2->3->6->9即可。当然这种递增路径不是唯一的。示例2
输入:
[[1,2],[4,3]]返回值:
4说明:
1->2->3->4备注:
矩阵的长和宽均不大于1000,矩阵内每个数不大于1000
2.解题思路
如果想知道当前位置mat[i][j]的最长递增路径的长度,它需要递归的访问它上下左右四个邻居结点,找到这四个邻居中最大的那个+1,即为当前结点的最长递增路径的长度。在访问前面结点的过程中,就把后面结点的结果保存进了res中,而后面再用到某一个位置的值时,就无需重复访问,直接返回原来记录的内容即可,这个过程就叫做记忆化搜索。
3.代码实现
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 递增路径的最大长度
* @param matrix int整型二维数组 描述矩阵的每个数
* @return int整型
*/
public int solve(int[][] matrix) {
// write code here
if (matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int ans = 0;
int n = matrix.length;
int m = matrix[0].length;
int[][] res = new int[n][m];
boolean[][] visited = new boolean[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
ans = Math.max(ans, dfs(matrix, i, j, res, visited));
}
}
return ans;
}
public int dfs(int[][] mat, int x, int y, int[][] res, boolean[][] visited) {
//如果当前位置已经记录了结果,直接返回
if (res[x][y] != 0) {
return res[x][y];
}
//否则,求出这个位置的最长递增路径长度
visited[x][y] = true;
int[] dx = {0, 0, -1, 1};
int[] dy = {-1, 1, 0, 0};
int len = 0;
int n = mat.length;
int m = mat[0].length;
for (int i = 0; i < dx.length; i++) {
int nx = dx[i] + x;
int ny = dy[i] + y;
if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny] &&
mat[nx][ny] > mat[x][y]) {
len = Math.max(len, dfs(mat, nx, ny, res, visited));
}
}
res[x][y] = len + 1;
visited[x][y] = false;
return res[x][y];
}
}