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
    
  • 相关阅读:
    智器SmartQ T7实体店试用体验
    BI笔记之SSAS库Process的几种方案
    PowerTip of the Day from powershell.com上周汇总(八)
    PowerTip of the Day2010071420100716 summary
    PowerTip of the Day from powershell.com上周汇总(十)
    PowerTip of the Day from powershell.com上周汇总(六)
    重新整理Cellset转Datatable
    自动加密web.config配置节批处理
    与DotNet数据对象结合的自定义数据对象设计 (二) 数据集合与DataTable
    在VS2003中以ClassLibrary工程的方式管理Web工程.
  • 原文地址:https://www.cnblogs.com/libbin/p/numIslands.html
Copyright © 2011-2022 走看看