zoukankan      html  css  js  c++  java
  • 200. 岛屿数量 BFS+DFS+并查集(Python 3)

    给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。

    示例 1:

    输入:
    11110
    11010
    11000
    00000
    
    输出: 1
    

    示例 2:

    输入:
    11000
    11000
    00100
    00011
    
    输出: 3
    

    本题根本是求连通域个数

    • 循环实现广度优先BFS(使用队列):
    from collections import deque
    
    class Solution:
        directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
        
        def numIslands(self, grid: List[List[str]]) -> int:
            m = len(grid) #行
            if m == 0:
                return 0
            n = len(grid[0]) # 列
            marked = [[False for i in range(n)] for i in range(m)]
            count = 0
            
            for i in range(m):
                for j in range(n):
                    if not marked[i][j] and grid[i][j] == '1':
                        queue = deque()
                        count += 1
                        queue.append((i,j))
                        marked[i][j] = True
                        while queue:
                            cur_x, cur_y = queue.popleft() # key step
                            for direction in self.directions:
                                new_i = cur_x + direction[0]
                                new_j = cur_y + direction[1]
                                if 0 <= new_i < m and 0 <= new_j < n and not marked[new_i][new_j] and grid[new_i][new_j] == '1':
                                    queue.append((new_i, new_j))
                                    marked[new_i][new_j] = True
            return count
    
    • 循环实现深度优先DFS(使用栈):
    class Solution:
        directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
    
        def numIslands(self, grid: List[List[str]]) -> int:
            count = 0
            m = len(grid)
            if m == 0:
                return 0
            n = len(grid[0])
            marked = [[False for i in range(n)] for i in range(m)]
            for i in range(m):
                for j in range(n):
                    if not marked[i][j] and grid[i][j] == '1':
                        stack = []
                        stack.append((i, j))
                        marked[i][j] = True
                        count += 1
                        while stack:
                            cur_i, cur_j = stack.pop()
                            for direction in self.directions:
                                new_i = cur_i + direction[0]
                                new_j = cur_j + direction[1]
                                if 0 <= new_i < m and 0 <= new_j < n and not marked[new_i][new_j] and grid[new_i][new_j] == '1':
                                    stack.append((new_i, new_j))
                                    marked[new_i][new_j] = True
            return count
    
    • 递归实现DFS方法:
    class Solution:
        directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
    
        def find(self, grid: List[List[str]], i, j):
            if i < 0 or i >= len(grid) or j < 0 or j >= len(grid[0]) or grid[i][j] != '1':
                return
            grid[i][j] = '2'
            for direction in self.directions:
                self.find(grid, i + direction[0], j + direction[1])
        
        def numIslands(self, grid: List[List[str]]) -> int:
            count = 0
            m = len(grid)
            if m == 0:
                return 0
            n = len(grid[0])
            for i in range(m):
                for j in range(n):
                    if grid[i][j] == '1':
                        self.find(grid, i, j)
                        count += 1
            return count
    
    • 并查集,只考虑向右和向下两个方向,而不是四个方向
    from typing import List
    class Solution:
        # 并查集
        
        def numIslands(self, grid: List[List[str]]) -> int:
            # 每个节点表示集合的一个元素,每个元素用一个数字表示
            class UnionFind:
                def __init__(self, n: int):
                    self.count = n
                    self.parent = [i for i in range(n)] # 每个元素的树根,开始时为自身
                    self.rank = [1 for _ in range(n)] # 每个节点的初始秩
                
                def getCount(self) -> int:
                    return self.count
                
                def find(self,p): # 递归寻找树根
                    if(p != self.parent[p]):
                        self.parent[p] = self.find(self.parent[p])
                    return self.parent[p]
                
                def union(self, p, q): # 按秩合并,将具有较小秩的树根指向具有较大秩的树根
                    p_root = self.find(p)
                    q_root = self.find(q)
                    if p_root == q_root:
                        return
                    if self.rank[p_root] > self.rank[q_root]:
                        self.parent[q_root] = p_root
                        self.rank[p_root] += 1
                    else:
                        self.parent[p_root] = q_root
                        self.rank[q_root] += 1
                    self.count -= 1
            
            m = len(grid)
            if m == 0:
                return 0
            n = len(grid[0])
    
            def getIndex(x, y):
                return x * n + y
    
            uf = UnionFind(m * n)
            water = 0
    
            for i in range(m):
                for j in range(n):
                    if grid[i][j] == '0':
                        water += 1
                    else:
                        if i + 1 < m and grid[i + 1][j] == '1':
                            uf.union(getIndex(i, j), getIndex(i + 1, j))
                        if j + 1 < n and grid[i][j + 1] == '1':
                            uf.union(getIndex(i, j), getIndex(i, j + 1))
    
            return uf.getCount() - water
    
  • 相关阅读:
    C# 调试
    C#添加资源的两种方式
    C# 光标文件的创建
    窗体初始位置
    C# 实现关闭按钮隐藏窗体而不退出
    mac ssd开启trim模式
    iOS打包上传app store各种问题解决总结
    adhoc无法下载应用程序 此时无法安装-解决
    debug1: expecting SSH2_MSG_KEX_ECDH_REPLY解决
    Could not load OpenSSL解决
  • 原文地址:https://www.cnblogs.com/libbin/p/numIslands.html
Copyright © 2011-2022 走看看