题目主要信息:
- 给定一个矩阵,矩阵中所有元素都是非负整数
- 需要在矩阵中找到一条最长路径,路径中的元素都是递增的,求其最长长度
- 查找路径时,只能向上下左右四个方向查找,不能超出边界,且每个格子最多走一次
具体思路:
既然是查找最长的递增路径长度,那我们首先要找到这个路径的起点,起点不好直接找到,就从上到下从左到右遍历矩阵的每个元素,然后以每个元素都可以作为起点查找它能到达的最长递增路径,然后维护一个最大值。
如何查找以某个点为起点的最长递增路径呢?我们可以考虑递归,因此我们查找递增路径的时候,每次选中路径一个点,然后找到与该点相邻的递增位置,相当于进入这个相邻的点,继续查找递增路径,这就是递归的子问题。因此递归过程如下:
- 终止条件: 进入路径最后一个点后,四个方向要么是矩阵边界,要么没有递增的位置,路径不能再增长,返回上一级。
- 返回值: 每次返回的就是本级之后的子问题中查找到的路径长度加上本级的长度。
- 本级任务: 每次进入一级子问题,先初始化后续路径长度为0,然后遍历四个方向(可以用数组表示,下标对数组元素的加减表示去往四个方向),进入符合不是边界且在递增的邻近位置作为子问题,查找子问题中的递增路径长度。因为有四个方向,所以最多有四种递增路径情况,因此要维护当级子问题的最大值。
具体过程可以参考如下图示:
代码实现:
class Solution {
public:
int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};//记录四个方向
int n, m;
//深度优先搜索,返回最大单元格数
int dfs(vector<vector<int> > &matrix,int i, int j) {
int length = 0;
for (int k = 0; k < 4; k++) {
int nexti = i + dirs[k][0];
int nextj = j + dirs[k][1];
//判断条件
if (nexti >= 0 && nexti < n && nextj >= 0 && nextj < m && matrix[nexti][nextj] > matrix[i][j]) {
length = max(length, dfs(matrix, nexti, nextj));
}
}
return length + 1;
}
int solve(vector<vector<int> >& matrix) {
if (matrix.size() == 0 || matrix[0].size() == 0) //矩阵不为空
return 0;
int res = 0;
n = matrix.size();
m = matrix[0].size();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
res = max(res, dfs(matrix, i, j)); //更新最大值
}
}
return res;
}
};
复杂度分析:
- 时间复杂度:,遍历矩阵每个元素复杂度是,对于矩阵每个元素进行一次递归,最坏情况递归经过整个矩阵,也需要
- 空间复杂度:,递归栈最大深度为矩阵展开大小