题目来源于leetcode,解法和思路仅代表个人观点。传送门。
难度:困难
用时:01:30:00
给定一个整数矩阵,找出最长递增路径的长度。
对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。
示例 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]。注意不允许在对角线方向上移动。
解法一(深度遍历+记忆优化):
如果只是进行深度遍历的话,会超时。所以需要使用数组记录一些东西。
仔细分析就会发现,每个点的最长递增路径是固定的。所以,可以使用一个相同大小的数组,保存每个点的最长递增路径。当访问该点时,如果数组值不为0,就返回当前点的数组值。
class Solution {
//上下左右
int[][] direction = {{0,1},{0,-1},{-1,0},{1,0}};
public int longestIncreasingPath(int[][] matrix) {
//空数组时
if (matrix.length == 0) return 0;
//标记当前点的最长递增路径
int[][] mark = new int[matrix.length][matrix[0].length];
int maxAscentLength=0;
//遍历每一个节点,对其进行dfs
for(int i=0;i<matrix.length;i++){
for(int j=0;j<matrix[0].length;j++){
int length = dfs(i,j,matrix,mark);
if(maxAscentLength<length){
maxAscentLength = length;
}
}
}
return maxAscentLength;
}
//深度遍历
private int dfs(int i,int j,int[][] matrix,int[][] mark){
int up = 0;
int down = 0;
int left = 0;
int right = 0;
//返回当前点的最长路径
if(mark[i][j] != 0){
return mark[i][j];
}
//遍历四个方向
//不走这个方向的条件
//1.到边界尽头
//2.找不到递增路径
//上
int row = i+direction[0][0];
int col = j+direction[0][1];
if(row>=0&&row<matrix.length){
if(col>=0&&col<matrix[0].length){
if(matrix[i][j]<=matrix[row][col]){
up = 0;
}else{
up = dfs(row,col,matrix,mark);
}
}
}
//下
row = i+direction[1][0];
col = j+direction[1][1];
if(row>=0&&row<matrix.length){
if(col>=0&&col<matrix[0].length){
if(matrix[i][j]<=matrix[row][col]){
down = 0;
}else{
down = dfs(row,col,matrix,mark);
}
}
}
//左
row = i+direction[2][0];
col = j+direction[2][1];
if(row>=0&&row<matrix.length){
if(col>=0&&col<matrix[0].length){
if(matrix[i][j]<=matrix[row][col]){
left = 0;
}else{
left = dfs(row,col,matrix,mark);
}
}
}
//右
row = i+direction[3][0];
col = j+direction[3][1];
if(row>=0&&row<matrix.length){
if(col>=0&&col<matrix[0].length){
if(matrix[i][j]<=matrix[row][col]){
right = 0;
}else{
right = dfs(row,col,matrix,mark);
}
}
}
//四个方向中,最长的递增长度
int maxLength = Math.max(Math.max(up,down),Math.max(left,right));
//更新mark数组(该点的最长长度)
mark[i][j] = maxLength;
return maxLength+1;
}
}
时间复杂度:O(mn),其中 mm 和 nn 分别是矩阵的行数和列数。 深度优先搜索的时间复杂度是 O(V+E),其中 V是节点数,E 是边数。
空间复杂度:O(mn),其中 mm 和 nn 分别是矩阵的行数和列数。 缓存空间复杂度是O(mn), 递归调用深度不会超过mn。