130. 被围绕的区域

https://leetcode-cn.com/problems/surrounded-regions/

解法一:dfs

两次遍历。第一次先遍历边界,dfs将所有与边界O相连的O置为‘-’。之后再遍历所有,将所有O变为X,所有’-‘变为O

class Solution:
    def solve(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        n = len(board)
        if n == 0:
            return
        m = len(board[0])
        #对四条边界上的元素dfs遍历
        for i in range(n):            
            self.dfs(i, 0, n, m, board)
            self.dfs(i, m-1, n, m, board)
        for j in range(m):
            self.dfs(0, j, n, m, board)
            self.dfs(n-1, j, n, m, board)
        #遍历所有
        for i in range(n):
            for j in range(m):
            	#注意先后顺序不能颠倒
                if board[i][j] == 'O':
                    board[i][j] = 'X'
                if board[i][j] == '-':
                    board[i][j] = 'O'
        
    def dfs(self, row, col, rows, cols, board):
        if row >= 0 and row < rows and col >= 0 and col < cols and board[row][col] == 'O':
            board[row][col] = '-'  #特殊标记
            #dfs遍历上下左右
            self.dfs(row, col-1, rows, cols, board)
            self.dfs(row, col+1, rows, cols, board)
            self.dfs(row-1, col, rows, cols, board)
            self.dfs(row+1, col, rows, cols, board)   

解法二:并查集

参考https://leetcode-cn.com/problems/surrounded-regions/solution/bfsdi-gui-dfsfei-di-gui-dfsbing-cha-ji-by-ac_pipe/

被x包围的o一定不与外界(设为“虚拟节点”)连通,例如边界的o与外界连通。用并查集找出不与外界连通的o,然后置为x即可。

优化

一、路径压缩

并查集的find函数可以改进

如下图

调用 find 函数每次向树根遍历的同时,顺手将树高缩短了,最终所有树高都不会超过 3(union 的时候树高可能达到 3)。

二、平衡性优化

我们一开始就是简单粗暴的把 p 所在的树接到 q 所在的树的根节点下面,那么这里就可能出现「头重脚轻」的不平衡状况,比如下面这种局面

长此以往,树可能生长得很不平衡。我们希望小一些的树接到大一些的树下面,这样就能避免头重脚轻,更平衡一些。解决方法是额外使用一个 size 数组,记录每棵树包含的节点数,称为“重量”(size)

最后更新于