例题1
所有可能的路径:给你一个有 n
个节点的 有向无环图(DAG),请你找出所有从节点 0
到节点 n-1
的路径并输出(不要求按特定顺序)
graph[i]
是一个从节点 i
可以访问的所有节点的列表(即从节点 i
到节点 graph[i][j]
存在一条有向边)。
深搜三部曲
其实dfs的过程就是回溯算法的过程,框架是相通的
void dfs(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本节点所连接的其他节点) {
处理节点;
dfs(图,选择的节点); // 递归
回溯,撤销处理结果
}
}
1.确定递归函数及参数
在该题中,递归函数的参数是graph二维数组跟当前结点x。
2. 确定终止条件
终止条件是当目前搜索到的路径没有下一个能访问的结点时,将该路径结果存储。所以终止条件是该结点为graph数组的最后一个元素。
3.处理目前搜索节点出发的路径
每一次搜索中,先找当前节点x的邻接点有哪些,故遍历该结点的邻接结点graph[x][i],在每一轮遍历中,将一个邻接点加入当前路径。再以邻接点为当前结点x,继续深搜,进入下一层递归,当递归结束并保存了遍历路径时,再进行回溯,撤销本节点。
code
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
path.push_back(0);
dfs(graph,0);//当前结点是0
return result;
}
void dfs(vector<vector<int>>& graph,int x)
{
//找出所有从节点 0 到节点 n-1 的路径,故graph.size()-1为结点个数
if(x == graph.size()-1)
{
result.push_back(path);
return ;
}
for(int i=0 ;i < graph[x].size() ; i++)
{
path.push_back(graph[x][i]);
dfs(graph,graph[x][i]);
path.pop_back();
}
}
};
例题2
给你一个由 '1'
(陆地)和 '0'
(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
深搜三部曲
1.确定递归函数及参数
在该题中,递归函数的参数是graph二维数组/当前结点x,y/是否访问过数组visted。
2. 确定终止条件
处理函数numIslands中,我们对没有访问过的陆地结点先进行计数,每计数一次,则把该结点的连通节点全部标为ture,即已访问过。在后续的计数过程中不计入这些连通结点。终止条件是当目前搜索到的路径没有下一个能访问的结点时(即当前节点已经访问过或者当前节点是海洋而不是陆地)。
3.处理目前搜索节点出发的路径
每一次搜索中,先访问结点(x,y)并将对应的visited数据元素置为true,然后深度搜索该结点的的正下方结点,再将该结点变为当前结点x,置为true后继续深搜,进入下一层递归,当递归结束后,再搜索当前结点的右/上/左边的结点并分别深搜。
code
class Solution {
public:
int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 四个方向
int numIslands(vector<vector<char>>& grid) {
int n = grid.size(), m = grid[0].size();
vector<vector<char>> visited(n,vector<char>(m,false));//是否已访问过
int res = 0;//岛屿数量
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
if(!visited[i][j] && grid[i][j] == '1')//未访问过而且是陆地不是海
{
res++;//岛屿数量加一
dfs(grid,visited,i,j);//将这块陆地的邻接陆地全标为true,不参与下次的遍历
}
}
return res;
}
void dfs(vector<vector<char>>& grid,vector<vector<char>>& visited,int x,int y)
{
//深度遍历 x,y 结点的邻接点,将这些节点设为 访问过
if(grid[x][y] == '0' || visited[x][y])//访问过此节点或碰到海水
return;
visited[x][y] = true;
for(int i = 0; i < 4; i++)
{
int nextx = x + dir[i][0];
int nexty = y + dir[i][1];
if(nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size())
continue;//越界,查看往其他地方走能不能行
dfs(grid,visited,nextx,nexty);
}
}
};