• [英雄星球六月集训LeetCode解题日报] 第26日 并查集


    日报

    • 今天的题都比较朴素,并查集的基础应用。

    题目

    一、 1559. 二维网格图中探测环

    链接: 1559. 二维网格图中探测环

    1. 题目描述

    在这里插入图片描述

    2. 思路分析

    • 对于网格里每对相邻的格子,如果他们值相同,就可以连接起来。
    • 那么我们朝单方向连接即可:
      • 对于每个格子我们连接它的上方和左方。
      • 不能连右和下的原因是:移到下一个格子的时候会产生重复处理。

    3. 代码实现

    class UnionFind:
        def __init__(self,size):
            self.fathers = list(range(size))
        def find_father(self,x):
            return self._zip_find_father(x)    
        def _zip_find_father(self,x):
            fathers = self.fathers
            if fathers[x] != x:
                fathers[x] = self._zip_find_father(fathers[x])
            return fathers[x]                      
        def union(self,x,y):
            x = self.find_father(x)
            y = self.find_father(y)
            if x == y:
                return False
            self.fathers[x] = y       
            return True 
    class Solution:
        def containsCycle(self, grid: List[List[str]]) -> bool:
            m,n = len(grid),len(grid[0])
            uf = UnionFind(m*n)
            for i in range(m):
                for j in range(n):
                    if i > 0:
                        if grid[i][j] == grid[i-1][j] and not uf.union(i*n+j,(i-1)*n+j):
                            return True
                    if j > 0:
                        if grid[i][j] == grid[i][j-1] and not uf.union(i*n+j,i*n+j-1):
                            return True
            return False
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述

    二、 1391. 检查网格中是否存在有效路径

    链接: 1391. 检查网格中是否存在有效路径

    1. 题目描述

    在这里插入图片描述

    2. 思路分析

    用并查集处理所有网格,最后检查起始点和结束点是否连通即可(祖宗相同)。

    • 这题特殊之处就是要全部特判相邻网格是否连通,v=grid[i][j]:
      • v==1时:它只能左右移动,且向左移动时,左边只能连接1、4、6;向右移动时,右边只能连接1、3、5。
      • v==其它时,均需特判。
      • 为了代码简洁,我们给1-6编号为0-5,用列表储存这6中情况分别对应的方向和方向上能连接的网格值。
      • 然后就是遍历所有网格并且让他们移动,判断移动后的网格符合条件就合并家族即可。

    3. 代码实现

    class UnionFind:
        def __init__(self,size):
            self.fathers = list(range(size))
        def find_father(self,x):
            return self._zip_find_father(x)    
        def _zip_find_father(self,x):
            fathers = self.fathers
            if fathers[x] != x:
                fathers[x] = self._zip_find_father(fathers[x])
            return fathers[x]                      
        def union(self,x,y):
            x = self.find_father(x)
            y = self.find_father(y)
            if x == y:
                return False
            self.fathers[x] = y       
            return True 
        def is_same_father(self,x,y):
            return self.find_father(x)==self.find_father(y)
    class Solution:
        def hasValidPath(self, grid: List[List[int]]) -> bool:
            m,n = len(grid),len(grid[0])
            uf = UnionFind(m*n)
            def in_bound(x,y):
                return 0<=x<m and 0<=y<n
            def hashed(x,y):
                return x*n+y
            left = {1,4,6}
            right = {1,3,5}
            top = {2,3,4}
            bottom = {2,5,6}
            dirs = [  # 6个方块分别能走的方向
                [(0,1),(0,-1)],  # 右左
                [(1,0),(-1,0)],  # 下上
                [(0,-1),(1,0)],  # 左下
                [(0,1),(1,0)],   # 右下
                [(-1,0),(0,-1)], # 上左
                [(0,1),(-1,0)],  # 右上
            ]
            accepts = [  # 6个方块按方向走后,能连通的合法块
                [right,left],
                [bottom,top],
                [left,bottom],
                [right,bottom],
                [top,left],
                [right,top],
            ]
            for i in range(m):
                for j in range(n):
                    k = grid[i][j] - 1  # 用来索引这个块的属性
                    for z in range(2):  # 走他能走的两个方向
                        x,y = i+dirs[k][z][0],j+dirs[k][z][1]
                        accept = accepts[k][z]
                        if in_bound(x,y) and grid[x][y] in accept:
                            uf.union(hashed(i,j),hashed(x,y))
    
            return uf.is_same_father(hashed(0,0),hashed(m-1,n-1))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    在这里插入图片描述

    三、 1202. 交换字符串中的元素

    链接: 1202. 交换字符串中的元素

    1. 题目描述

    在这里插入图片描述

    2. 思路分析

    • 我们用并查集把可以互相交换的字符合并为家族。
    • 显然同一家族中的字符可以任意摆放。
    • 那么我们对每个家族内部排序,然后按顺序填回他们家族的位置即可。
    • 为了Python方便比较大小和转换,我先把所有字母变成ASCII码,最后拼接时再转回来。

    3. 代码实现

    class UnionFind:
        def __init__(self,size):
            self.fathers = list(range(size))
        def find_father(self,x):
            return self._zip_find_father(x)    
        def _zip_find_father(self,x):
            fathers = self.fathers
            if fathers[x] != x:
                fathers[x] = self._zip_find_father(fathers[x])
            return fathers[x]                      
        def union(self,x,y):
            x = self.find_father(x)
            y = self.find_father(y)
            if x == y:
                return False
            self.fathers[x] = y       
            return True 
        def is_same_father(self,x,y):
            return self.find_father(x)==self.find_father(y)
    class Solution:
        def smallestStringWithSwaps(self, s: str, pairs: List[List[int]]) -> str:
            ss = [ord(c) for c in s]
            n = len(ss)
            uf = UnionFind(n)
            for a,b in pairs:
                uf.union(a,b)
            familys = defaultdict(list)
            for i in range(n):
                familys[uf.find_father(i)].append(i)
            
            ans = [0]*n
            for ps in familys.values():
                ps2 = sorted(ps,key=lambda x:ss[x])            
                # print (ps,ps2)
                for i in range(len(ps)):
                    ans[ps[i]] = ss[ps2[i]] 
            
            return ''.join(chr(c) for c in ans)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
  • 相关阅读:
    记一次语音播报功能
    【校招VIP】高校陌生人活动|产品的竞品和需求分析
    基于 Docker CICD 的 Master Slave 架构应用
    《职场求生攻略》
    如何将您的网站添加到百度站长工具
    CTF竞赛题解之stm32逆向入门
    【概率论】斗地主中出现炸弹的几率
    深度学习网络模型——DenseNet模型详解与代码复现
    java计算机毕业设计ssm建设路小学芙童币和芙童印章管理系统(源码+系统+mysql数据库+Lw文档)
    MySQL 的 limit 分页查询及性能问题
  • 原文地址:https://blog.csdn.net/liuliangcan/article/details/125473801