深度优先搜索

73 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 23 天,点击查看活动详情

dfs也叫深度优先遍历,一般用于图或者树的遍历,或者二维矩阵也常用它。它的原理是,从初始点开始,一直沿着一个方向遍历,直到走到底,然后线上回溯一级,借助一个分支走到底,再次回溯,如此往复,直到所有节点都被访问过。

最经典的是岛屿问题

比如给一个矩阵(只包括01),1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。

岛屿: 相邻陆地可以组成一个岛屿(相邻:上下左右) 判断岛屿个数。

例如: 输入

[

[1,1,0,0,0],

[0,1,0,1,1],

[0,0,0,1,1],

[0,0,0,0,0],

[0,0,1,1,1]

]

那么岛屿数为3.

那么本题思路可以是,当我们找到当前值为1,先把他置于0,然后对他上下左右都进行遍历,如果有一个方向县不是1,那么就结束当前方向,当所有方向都是0后,岛屿数++。在对上下左右进行遍历时候,如果当前值为1,先把他置于0,然后对他上下左右都进行遍历,如果有一个方向县不是1,那么就结束当前方向......

后续四个方向遍历模板:

if(i-1>=0 && grid[i-1][j]=='1'){
dfs(grid,i-1,j)
}

如果这个方向没有超出边界,并且这个方向值为1,那么这个当前点继续dfs搜索。

那么你可能会问:比如a下一个b是的,b再次dfs不会遇到a吗?

这就是为什么在找到当前值是1后,需要把他修改成为其他值的原因。

那么这个dfs结束条件:当前值4个方向都没有1,也不需要递归,就直接返回,或者到达了矩阵边缘。

具体做法:先判断特殊情况,即矩阵为空,然后对数组进行从上到下,从左到右的遍历。如果当前值为1,就统计岛数,并且把该位置值修改,然后调用dfs判断四个方向。

image.png

矩阵最长递增路径

本题也是二维矩阵dfs问题。 image.png

结束条件:到达矩阵边缘,或者几个方向上没有递增位置了。

因为防护最长递增路径,我们可以直接用max,但是为了记录初始位置,我们可以同时声明一个dp数组,用来统计某个位置dfs下去的最大长度。

具体做法:先判断矩阵是不是空矩阵,如果不是空,就定义一个最大长度变量,并且新加一个dp二维数组,最大长度变量就等于这个数组里面最大值。

最大值需要dfs。传入参数,原二维数组,dp数组,当前位置i,j。 因为dp就是当前值对于递增长度,所以如果dp不是0,就代表当前值有递增长度。

否则代表还需继续增加。如果当前值的下一个位置比他大,那么dp就需要继续寻找max,并且递归调用dfs

image.png

总结::dfs需要我们考虑递归结束条件,返回值类型,还有当前层做了声明。怎么和下一级调用等

dfs模板如下:

void dfs() {
if(到达终点状态)
{
//做什么 return;
}
if(越界或者是不合法状态)
return; for(扩展方式)
{
if(扩展方式所达到状态合法)
{
修改操作;
dfs();
}
}
}