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 board
m = len(board[0])
def dfs(i, j):
if not 0 <= i < n or not 0 <= j < m:
return
if board[i][j] != 'O':
return
board[i][j] = '#'
dfs(i - 1, j)
dfs(i + 1, j)
dfs(i, j - 1)
dfs(i, j + 1)
for i in range(n):
dfs(i, 0)
dfs(i, m - 1)
for j in range(m):
dfs(0, j)
dfs(n - 1, j)
for i in range(n):
for j in range(m):
if board[i][j] == '#':
board[i][j] = 'O'
elif board[i][j] == 'O':
board[i][j] = 'X'
棋盘是二维的, 每个位置的祖先编号仍然是一个数值, 因此我们需要将每个二维坐标映射到一维的唯一数字, 常用的方法就是位置递增编号, 对于二维坐标(x, y), 映射为x * m + y, 其中m是二维矩阵的列数. 这样共得到0, 1, ..., m * n - 1这些编号索引. 再加上上面说的边界上的O的共同祖先, 我们将其定义为m * n, 这种就得到了共m * n + 1个编号.
使用普通的并查集方法对齐进行查找合并, 最终遍历所有O的位置, 判断其最先是否为m * n, 对于不是的填充为X.
class Union:
def __init__(self, n):
self.roots = list(range(n))
def find(self, i):
if self.roots[i] == i:
return i
self.roots[i] = self.find(self.roots[i])
return self.roots[i]
def union(self, a, b):
self.roots[self.find(a)] = self.find(b)
def connected(self, a, b):
return self.find(a) == self.find(b)
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 board
m = len(board[0])
dummy = m * n
u = Union(m * n + 1)
for i in range(n):
if board[i][0] == 'O':
u.union(i * m, dummy)
if board[i][m - 1] == 'O':
u.union(i * m + m - 1, dummy)
for j in range(m):
if board[0][j] == 'O':
u.union(j, dummy)
if board[n - 1][j] == 'O':
u.union((n - 1) * m + j, dummy)
directs = [(-1, 0), (1, 0), (0, -1), (0, 1)]
for i in range(n):
for j in range(m):
if board[i][j] == 'O':
for row, col in directs:
if 0 <= i + row < n and 0 <= j + col < m and board[i + row][j + col] == 'O':
u.union((i + row) * m + j + col, i * m + j)
for i in range(n):
for j in range(m):
if board[i][j] == 'O' and not u.connected(i * m + j, dummy):
board[i][j] = 'X'