面试热点题:LeetCode岛屿问题DFS 岛屿的数量、周长、最大面积

关于DFS(深度优先搜索)

我们了解到的DFS一般是在树或者图这样的结构上进行搜索的,那么我们如何将其运用在这样类似网格的地方进行搜索呢?

如下网格:
在这里插入图片描述

网格问题是由 m×n 个小方格组成一个网格,每个小方格与其上下左右四个方格认为是相邻的,要在这样的网格上进行某种搜索

DFS结构

网格问题相较于二叉树的结构稍复杂一点,要写好网格上的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)岛屿的周长

在这里插入图片描述
这一个题与上面的遍历思路差不多,主要是关于周长的判断:

周长判断思路1:
在这里插入图片描述
周长判断思路2:
在这里插入图片描述
参考代码:

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;
    }
};

猜你喜欢

转载自blog.csdn.net/DEXTERFUTIAN/article/details/129880606