1 介绍
参考之前的链接:深度优先(DFS)_hclbeloved的博客-CSDN博客
深度优先为了防止重复访问,需要一个visited数组来记录之前已经走过的路,从而起到防止走回头路的作用。现有个题目在DFS中使用到了备忘录(类似于从上到下的动态规划中的备忘录)。
注意:从上到下的动态规划使用的也是递归,而DFS使用的也是递归。
2 矩阵中的最长递增路径
2.1 传统的DFS求解
class Solution {
public:
int longestIncreasingPath(vector<vector<int>>& matrix) {
// 方法一:使用传统的DFS超出时间限制
int n = matrix.size(), m = matrix[0].size();
vector<vector<bool>> visited(n, vector<bool>(m, false));
int maxLength = 0;
for (int i=0;i<n;++i)
{
for (int j=0;j<m;++j)
{
maxLength = std::max(maxLength, dfs(matrix, i, j, 1, memo));
}
}
return maxLength;
}
};
int dfs(vector<vector<int>>& matrix, int r, int c, int count, vector<vector<bool>>& visited)
{
if (visited[r][c])
return count;
visited[r][c] = true;
int maxLength = count;
vector<pair<int,int>> neighbours{{-1,0},{1,0},{0,-1},{0,1}};
int n = matrix.size(), m = matrix[0].size();
for (auto& item : neighbours)
{
int x = r + item.first, y = c + item.second;
if (x < 0 || x >= n || y < 0 || y >= m || matrix[x][y] <= matrix[r][c])
continue;
maxLength = std::max(maxLength, dfs(matrix, x, y, count+1, visited));
}
visited[r][c] = false;
return maxLength;
}
2.2 带有备忘录的DFS求解
class Solution {
public:
int longestIncreasingPath(vector<vector<int>>& matrix) {
// 方法二:使用带有备忘录的DFS
int n = matrix.size(), m = matrix[0].size();
vector<vector<int>> memo(n, vector<int>(m, 0));
int maxLength = 0;
for (int i=0;i<n;++i)
{
for (int j=0;j<m;++j)
{
maxLength = std::max(maxLength, dfs(matrix, i, j, memo));
}
}
return maxLength;
}
};
//带有备忘录的DFS,同时备忘录起到了判断重复访问的作用
/* 链接:https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/solution/ju-zhen-zhong-de-zui-chang-di-zeng-lu-jing-by-le-2/
如果使用朴素深度优先搜索,时间复杂度是指数级,会超出时间限制,因此必须加以优化。
朴素深度优先搜索的时间复杂度过高的原因是进行了大量的重复计算,同一个单元格会被访问多次,每次访问都要重新计算。
由于同一个单元格对应的最长递增路径的长度是固定不变的,因此可以使用记忆化的方法进行优化。用矩阵 memo 作为缓存矩阵,已经计算过的单元格的结果存储到缓存矩阵中。
使用记忆化深度优先搜索,当访问到一个单元格 (i,j) 时,如果 memo[i][j]!=0,说明该单元格的结果已经计算过,则直接从缓存中读取结果;
如果 memo[i][j]=0,说明该单元格的结果尚未被计算过,则进行搜索,并将计算得到的结果存入缓存中。
遍历完矩阵中的所有单元格之后,即可得到矩阵中的最长递增路径的长度。
*/
int dfs(vector<vector<int>>& matrix, int r, int c, vector<vector<int>>& memo)
{
if (memo[r][c])
return memo[r][c];
++memo[r][c];
vector<pair<int,int>> neighbours{{-1,0},{1,0},{0,-1},{0,1}};
int n = matrix.size(), m = matrix[0].size();
for (auto& item : neighbours)
{
int x = r + item.first, y = c + item.second;
if (x < 0 || x >= n || y < 0 || y >= m || matrix[x][y] <= matrix[r][c])
continue;
memo[r][c] = std::max(memo[r][c], 1 + dfs(matrix, x, y, memo));
}
return memo[r][c];
}
3
4