【leetcode100】岛屿数量

1、题目描述

给你一个由 '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、岛屿(网格)类问题dfs方法

2.1 思路

岛屿类问题可以类比二叉树的dfs方法,首先,二叉树的dfs方法如下所示:

def dfs(node) {
    # 判断是否越界
    if (node == null) {
        return;
    }
    # 访问两个相邻结点
    dfs(node.left);
    dfs(node.right);
}

更详细的前、中、后序遍历可参考:【二叉树】遍历总结!_二叉树遍历所有路径-CSDN博客 

由此,网格类问题的dfs需要首先考虑两个问题:

(1) 如何遍历相邻的格子?

对二叉树来说,对网格类问题来说,(r,c)四个相邻的格子分别是(r-1,c)、(r+1,c)、(r,c-1)和(r,c+1)。

(r-1,c)
(r,c-1)(r,c)(r,c+1)
(r+1,c)

则其dfs结构可表示为:

dfs(r+1, c)
dfs(r-1, c)
dfs(r, c+1)
dfs(r, c-1)

 (2)如何防止越界问题?

在二叉树中,当访问到叶子节点时,不能再继续进行遍历;在网格类问题中,网格的四边都不能出界,即表示为:

m,n = len(grid), len(grid[0])
if r<0 or c<0 or r >= m or c >= n:
   return

但在网格类问题中,因为其在四周遍历的缘故,其可能会出现重复访问的情况,那么应该考虑第3个问题:

(3)如何防止重复访问?

答案是可以通过标记已经访问过的格子,从而防止重复遍历,通常将其标记为2。即:

  • 0 —— 海洋格子
  • 1 —— 陆地格子(未遍历过)
  • 2 —— 陆地格子(已遍历过)

理论上来说可以将访问过的格子标记为除1以外的任何数,但最好不要将其标记为0,此时,无法区分海洋格子和遍历过的陆地格子,在更复杂的题目中,可能会出错。

2.2 dfs代码

综上,岛屿问题的dfs代码可总结如下:

lass Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        m,n = len(grid), len(grid[0])
        def dfs(r,c ):
            if r<0 or c<0 or r >= m or c >= n or grid[r][c]!='1':
                return
            grid[r][c] = '2'
            dfs(r+1, c)
            dfs(r-1, c)
            dfs(r, c+1)
            dfs(r, c-1)
#'1'或1 根据题目实际情况

所有岛屿类问题,均可根据dfs算法进行分析求解

3 本题解法

3.1 思路

岛屿是与水平/竖直相邻的陆地连接而成,陆地的格子表示为1(未遍历),因此,可对网格中每个格子进行遍历,通过访问其周边的格子,并将访问过的陆地标记为2。则当遇到一个未被访问过的陆地('1')时,启动 DFS 来标记所有与之相连的陆地。每次启动 DFS 时,意味着发现了一个新的岛屿,因此岛屿数量加 1。当没有‘1’格子时,表示已经不存在新岛屿。

3.2 代码

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        m,n = len(grid), len(grid[0])
        def dfs(r,c ):
            if r<0 or c<0 or r >= m or c >= n or grid[r][c]!='1':
                return
            grid[r][c] = '2'
            dfs(r+1, c)
            dfs(r-1, c)
            dfs(r, c+1)
            dfs(r, c-1)
        res = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == '1':
                    dfs(i, j)
                    res += 1
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SsummerC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值