我们了解到的DFS一般是在树或者图这样的结构上进行搜索的,那么我们如何将其运用在这样类似网格的地方进行搜索呢?
网格问题是由 m×n 个小方格组成一个网格,每个小方格与其上下左右四个方格认为是相邻的,要在这样的网格上进行某种搜索
网格问题相较于二叉树的结构稍复杂一点,要写好网格上的DFS我们首先要熟悉一下二叉树的DFS
二叉树的DFS也包括二叉树的前中后序遍历
二叉树DFS基本结构:
void DFS(TreeNode root) {
//判断终止条件
if (root == null) {
return;
}
// 访问两个相邻结点:左子结点、右子结点
DFS(root->left);
DFS(root->right);
}
我们不难看出二叉树的DFS主要有两个要点:
那么网格结构也是类似的,网格以一个格子为中心,向上下左右遍历:
网格终止条件
网格DFS基本结构:
void dfs(vector<vector<int> grid, int i, int j) {
// 终止条件判断
// 如果坐标超出了网格范围,直接返回
if (终止条件)) {
return;
}
// 如果这个格子不是岛屿,直接返回
if (grid[i][j] != 1) {
return;
}
grid[i][j] = 2; // 将格子标记为「已遍历过」
// 访问上、下、左、右四个相邻结点
dfs(grid, i - 1, j);
dfs(grid, i + 1, j);
dfs(grid, i, j - 1);
dfs(grid, i, j + 1);
}
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
来源:力扣(LeetCode)岛屿数量
这是一个很典型的网格问题,要解决其实很简单:
思路:依次遍历grid数组,如果是’1’进入DFS递归,并且在递归中遍历其相邻的网格,并将网格的数字更改为’2’,递归结束,继续遍历grid数组。
传入DFS的函数参数的grid数组必须要是引用,这样才能真正标记grid已经计算过的岛屿,防止遍历grid数组遇到相同的岛屿,持续判断。
参考代码:
class Solution {
public:
void DFS(vector<vector<char>>& grid,int i,int j)
{
//终止条件判断
if(i < 0 || i >= grid.size() ||
j < 0 || j >= grid[0].size() || grid[i][j] != '1'){
return;
}
grid[i][j]='2';//已遍历标记
DFS(grid,i+1,j);
DFS(grid,i-1,j);
DFS(grid,i,j+1);
DFS(grid,i,j-1);
}
int numIslands(vector<vector<char>>& grid) {
int sum=0;
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid[0].size();j++)
{
if(grid[i][j]=='1')//只有'1'才进入 '0' 与 '2' 都不进入
{
sum++;
DFS(grid,i,j);
}
}
}
return sum;
}
};
给定一个 row x col 的二维网格地图 grid ,其中:grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。
网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。
岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。
来源:力扣(LeetCode)岛屿的周长
class Solution {
public:
int DFS(vector<vector<int>>& grid,int i,int j)
{
//边界+1
if(i<0 || i>=grid.size() || j<0 || j>=grid[0].size())
{
return 1;
}
//'0'海洋+1
if(grid[i][j]==0)
{
return 1;
}
//已遍历过的陆地+0
if(grid[i][j]!=1)
{
return 0;
}
grid[i][j]=2;
return DFS(grid,i-1,j)+
DFS(grid,i+1,j)+
DFS(grid,i,j-1)+
DFS(grid,i,j+1);
}
int islandPerimeter(vector<vector<int>>& grid) {
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid[0].size();j++)
{
if(grid[i][j]==1)
{
return DFS(grid,i,j);
}
}
}
return 0;
}
};
给你一个大小为 m x n 的二进制矩阵 grid 。
岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
岛屿的面积是岛上值为 1 的单元格的数目。
计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0
来源:力扣(LeetCode)岛屿的最大面积
这一题也是简单题,这类网格DFS问题,只要理清DFS结构,依葫芦画瓢写,其实不难。
思路:依次遍历,迭代最大的面积
参考代码:
class Solution {
public:
int DFS(vector<vector<int>>& grid,int i,int j)
{
if(i<0 || i>=grid.size() || j<0 || j>=grid[0].size() || grid[i][j]!=1)
{
return 0;
}
grid[i][j]=2;
return 1+DFS(grid,i+1,j)+
DFS(grid,i-1,j)+
DFS(grid,i,j+1)+
DFS(grid,i,j-1);
}
int maxAreaOfIsland(vector<vector<int>>& grid) {
int max=0;
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid[0].size();j++)
{
if(grid[i][j]==1)
{
int sum=DFS(grid,i,j);
if(sum>max)
{
max=sum;
}
}
}
}
return max;
}
};