leetcode 经典宽搜BFS深搜DFS题目(思路、方法、code)
BFS和DFS的经典应用就是在树和图中的遍历。
地图的搜索问题通常都可以用BFS和DFS解决,下面题目非常典型,并且很多题目类似,自己如果能够独立完成基本就掌握了BFS和DFS以及地图的遍历问题。
文章目录
-
-
- leetcode 经典宽搜BFS深搜DFS题目(思路、方法、code)
-
- [200. 岛屿数量](https://leetcode-cn.com/problems/number-of-islands/)
- [127. 单词接龙](https://leetcode-cn.com/problems/word-ladder/)
- [473. 火柴拼正方形](https://leetcode-cn.com/problems/matchsticks-to-square/)
- [103. 二叉树的锯齿形层次遍历](https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/)
- [130. 被围绕的区域](https://leetcode-cn.com/problems/surrounded-regions/)
- [994. 腐烂的橘子](https://leetcode-cn.com/problems/rotting-oranges/)
- [695. 岛屿的最大面积](https://leetcode-cn.com/problems/max-area-of-island/)
- [542. 01 矩阵](https://leetcode-cn.com/problems/01-matrix/)
-
200. 岛屿数量
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:
11110
11010
11000
00000
输出: 1
示例 2:
输入:
11000
11000
00100
00011
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。
分析:求解该问题,实际上就是要找多少个陆地区域,因此采用BFS、DFS两种方法均可遍历。核心思路在于,当发现一个陆地,需要将其上下左右四个方向所有可以延展到的陆地都要加入其中(可以直接将这些陆地变为海洋即可),根据此,遍历所有区域还要注意的是,这个题目的输入是 char 不是 int
BFS方法
通过一个队列,每次找到一个陆地后,进行BFS搜索,将该陆地所在的整体陆地地区全部更新为海洋。(需要注意的是,这里每次push进队列时,就直接将该位置赋值为海洋,否则会push进很多重复节点)
class Solution {
public:
int numIslands(vector< vector<char> >& grid)
{
if(grid.size()==0) return 0;
int result=0;
for(int i=0;i<grid.size();i++)
for(int j=0;j<grid[0].size();j++)
{
if(grid[i][j]=='1') //找到一个陆地就要把相连的全部变为水
{
result++;
queue< pair<int,int> > Q;
Q.push(make_pair(i,j)); //调用make_pair使(i,j)转化为pair
grid[i][j]='0'; //将该地区置为0
while(!Q.empty())
{
pair<int,int> top=Q.front();
Q.pop();
//接着把上下左右四个方向的陆地加进去
//注意push时候就要将其改为'0',要不然重复太多
if(top.first-1>=0&&grid[top.first-1][top.second]=='1')
{
grid[top.first-1][top.second]='0';
Q.push(make_pair(top.first-1,top.second));
}
if(top.second-1>=0&&grid[top.first][top.second-1]=='1')
{
grid[top.first][top.second-1]='0';
Q.push(make_pair(top.first,top.second-1));
}
if(top.first+1<grid.size()&&grid[top.first+1][top.second]=='1')
{
grid[top.first+1][top.second]='0';
Q.push(make_pair(top.first+1,top.second));
}
if(top.second+1<grid[0].size()&&grid[top.first][top.second+1]=='1')
{
grid[top.first][top.second+1]='0';
Q.push(make_pair(top.first,top.second+1));
}
}
}
}
return result;
}
};
DFS方法:
采用DFS递归深搜即可,思路与BFS一致,遍历方法不同而已。
class Solution {
void DFS(vector<vector<char>> &grid,int cur_i,int cur_j)
{
if(cur_i<0||cur_i==grid.size()||cur_j<0||cur_j==grid[0].size()||grid[cur_i][cur_j]=='0') return;
grid[cur_i][cur_j]='0'; //将其标记为海洋
int di[4]={
0,0,1,-1};
int dj[4]={
1,-1,0,0}; //方向数组
for(int index=0;index<4;index++) //四个方向遍历
{
DFS(grid,cur_i+di[index],cur_j+dj[index]); //找到一个陆地就直接继续深入搜索
}
return;
}
public:
int numIslands(vector<vector<char>>& grid) {
int ans=0;
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid[0].size();j++)
{
if(grid[i][j]=='1')
{
ans++;
DFS(grid,i,j);
}
}
}
return ans;
}
};
127. 单词接龙
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:每次转换只能改变一个字母。转换过程中的中间单词必须是字典中的单词。
说明:如果不存在这样的转换序列,返回 0。所有单词具有相同的长度。所有单词只由小写字母组成。
字典中不存在重复的单词。你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例 1:
输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
输出: 5
解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",
返回它的长度 5。
示例 2:
输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
输出: 0
解释: endWord "cog" 不在字典中,所以无法进行转换。
分析:(这个mid难度有点hard)
将单词之间的转换,理解为一张图,即如果两个单词之间可以转换(相差一个字母),就说明这两个单词之间