leetcode 200:岛屿数量

本文探讨了如何使用深度优先搜索(DFS)和并查集算法来计算给定由1和0组成的二维网格中岛屿的数量。两种方法分别介绍了详细步骤,并展示了如何在代码中实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:
给你一个由 ‘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
思路1:
通过染色法,若一个为1的区域是整个大区域的一部分将其值返回为0,一个岛屿的第一个1仍为1,其余为0,是一种扩散的思想。可以通过深搜和广搜两种方式实现。
DFS:以深度进行扩散
BFS:把结点放到一个queue里,取出一个把其相邻的四个中为1的加入队列中,直到整个队列为空。
深搜:

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        self.dx = [-1, 1, 0, 0]
        self.dy = [0, 0, -1, 1]
        self.grid = grid
        self.visited = set()
        m, n = len(grid), len(grid[0])
        res = [[0 for _ in range(len(grid[0]))] for _ in range(len(grid))]
        sum = 0
        for i in range(m):
            for j in range(n):
                res[i][j] = self.DFS(i, j)
                sum += res[i][j]
        return sum

    def DFS(self, i, j):
        if not self.is_valid(i, j):
            return 0
        self.visited.add((i, j))
        for k in range(4):
            self.DFS(i+self.dx[k], j+self.dy[k])
        return 1

    def is_valid(self, i, j):
        if i < 0 or j < 0 or i >= len(self.grid) or j >= len(self.grid[0]):
            return False
        if self.grid[i][j] == "0" or ((i, j) in self.visited):
            return False
        return True

广搜:

import collections


class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        self.dx = [-1, 1, 0, 0]
        self.dy = [0, 0, -1, 1]
        self.grid = grid
        self.visited = set()
        m, n = len(grid), len(grid[0])
        res = [[0 for _ in range(len(grid[0]))] for _ in range(len(grid))]
        sum = 0
        for i in range(m):
            for j in range(n):
                res[i][j] = self.BFS(i, j)
                sum += res[i][j]
        return sum

    def BFS(self, i, j):
        if not self.is_valid(i, j):
            return 0
        self.visited.add((i, j))
        queue = collections.deque()
        queue.append((i, j))
        while queue:
            x, y = queue.popleft()
            for k in range(4):
                nx, ny = x+self.dx[k], y+self.dy[k]
                if self.is_valid(nx, ny):
                    queue.append((nx, ny))
                    self.visited.add((nx, ny))
        return 1

思路2: 并查集
a. 初始化:所有为1的结点的根是自己
b. 遍历所有的结点,相邻的结点如为1进行合并根,为0时不需要进行操作,最后root是统计组的数量,可以在初始化和合并的过程中进行统计;如果采用最后进行一次遍历parent的话注意parent[0] = 0的处理。

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        if not grid or not grid[0]:
            return 0
        uf = UnionFind(grid)
        h = len(grid)
        l = len(grid[0])
        dx = [-1, 1, 0, 0]
        dy = [0, 0, -1, 1]
        for i in range(h):
            for j in range(l):
                if grid[i][j] == "1":
                    for d in range(4):
                        nx, ny = i+dx[d], j+dy[d]
                        if 0 <= nx < h and 0 <= ny < l and grid[nx][ny] == "1":
                            uf.union(i * l + j, nx * l + ny)
        return uf.count


class UnionFind(object):
    def __init__(self, grid):
        m = len(grid)
        n = len(grid[0])
        self.parent = [0] * (m*n)
        self.rank = [0] * (m*n)
        self.count = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == "1":
                    self.parent[i*n+j] = i*n+j
                    self.count += 1

    def find(self, i):
        while i != self.parent[i]:
            i = self.parent[i]
        return i

    def union(self, x, y):
        rootx = self.find(x)
        rooty = self.find(y)
        if rootx != rooty:
            if self.rank[rootx] < self.rank[rooty]:
                self.parent[rootx] = rooty
            elif self.rank[rootx] > self. rank[rooty]:
                self.parent[rooty] = rootx
            else:
                self.parent[rooty] = rootx
                self.rank[rootx] += 1
            self.count -= 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值