目录
前言
DFS是一种搜索可行解方式的方式,通常用于求"所有,全部..等一类问题",今天在写深度搜索问题时问题屡屡出现,搞得我怀疑自己以前学的到底有菜鸡......特此写下一篇手记,供大家参考,也供自己日后复习.
一、DFS的例题形式?
这里贴出最经典的一类问题,下面给出两道LeetCode原题:
①给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出:1
示例 2:
输入:grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出:3
②
你有一个用于表示一片土地的整数矩阵land,该矩阵中每个点的值代表对应地点的海拔高度。若值为0则表示水域。由垂直、水平或对角连接的水域为池塘。池塘的大小是指相连接的水域的个数。编写一个方法来计算矩阵中所有池塘的大小,返回值需要从小到大排序。
示例:
输入:
[
[0,2,1,0],
[0,1,0,1],
[1,1,0,1],
[0,1,0,1]
]
输出: [1,2,4]
提示:
0 < len(land) <= 1000
0 < len(land[i]) <= 1000
二、思路
分析
我们发现这两道题几乎是一模一样有没有?唯一的区别就是第二道题要求输出水域的大小,除此以外,一模一样!
我们如果直接上模板,很多同学会想:奇了怪了,这个东西怎么来的呢?不方便大家理解和吸收内化,那请大家接下来跟着我一起来构思一下整个过程!
首先说核心DFS函数--
递归三部曲:返回条件(写在递归头部),处理逻辑(中间),返回值
我们的返回条件有哪些?边界不越界+当前方格不满足条件(不是陆地(第二题)或者水洼(第一题))+已经访问过了,只要有一个条件满足,我们就直接返回.
处理逻辑:对于第一道题,将它的visited位置为true,第二道题,visited置为true+水洼大小加一.同时,我们需要对当前格子的周围格子进行递归.
返回值void
接下来说说包含DFS的题目函数.
逻辑很简单,我们只需要对二维数组进行循环DFS,只有当visited为false并且当前方格满足题目要求条件(比如说是陆地或者水洼),才进行DFS.
总结
void dfs(方格,当前行,当前列)
{
if(...若干个返回条件) return;
//中间逻辑
visited=true;
.....
for(int i=0;i<4(若是四周则是8);++i) dfs(....);
}
返回参数 题目函数名(二维vector)
{
for(int i....)
for(int j.....)
{
if(!visited[i][j]&&vector[i][j]==?) //这里可以是题目要求返回结果的值(比如水洼代表0 岛屿代表'1')
dfs(....);
}
}