# 构建trie trie = Trie() for word in words: trie.insert(word)
self.m, self.n = len(board), len(board[0]) for i inrange(self.m): for j inrange(self.n): if trie.children[ord(board[i][j]) - ord("a")] isnotNone: self._dfs(board, i, j, "", trie.children[ord(board[i][j]) - ord("a")] )
returnlist(self.result)
def_dfs(self, board, i, j, curr_word, trie): curr_word += board[i][j]
if trie.is_end: self.result.add(curr_word)
tmp, board[i][j] = board[i][j], '@' dx = [-1, 1, 0, 0] dy = [0, 0, -1, 1] for k inrange(len(dx)): x, y = i + dx[k], j + dy[k] if0 <= x < self.m and0 <= y < self.n and board[x][y] != '@' \ and trie.children[ord(board[x][y]) - ord('a')] isnotNone: self._dfs(board, x, y, curr_word, trie.children[ord(board[x][y]) - ord('a')]) board[i][j] = tmp
classSolution: defnumIslands(self, grid: List[List[str]]) -> int: """ 为了求出岛屿的数量,可以扫描整个二维网格。如果一个位置为 1, 则将其与相邻四个方向上的 111 在并查集中进行合并。 最终岛屿的数量就是并查集中连通分量的数目。 """ ifnot grid: return0 m = len(grid) n = len(grid[0]) # 初始化并查集 self.parent = [i for i inrange(m * n)] self.count =0 for i inrange(m): for j inrange(n): if grid[i][j] == "1": self.parent[i * n + j] = i * n + j self.count += 1
# 合并 dx = [-1, 1, 0, 0] dy = [0, 0, -1, 1] for i inrange(m): for j inrange(n): if grid[i][j] == "1": grid[i][j] = "0" for k inrange(len(dx)): x, y = i + dx[k], j + dy[k] if0 <= x < m and0 <= y < n and grid[x][y] == "1": self._union(i * n + j, x * n + y)
return self.count
def_union(self, i, j): p1 = self._parent(i) p2 = self._parent(j) if p1 == p2: return self.parent[p1] = p2 self.count -= 1
def_parent(self, i): root = i while self.parent[root] != root: root = self.parent[root] # 路径压缩 while self.parent[i] != i: x = i i = self.parent[i] self.parent[x] = root return root
classSolution: """ 把所有边界上的 O 看做一个连通区域。遇到 O 就执行并查集合并操作,这样所有的 O 就会被分成两类 1.和边界上的 O 在一个连通区域内的。这些 O 保留。 2.不和边界上的 O 在一个连通区域内的。这些 O 就是被包围的,替换。 由于并查集一般用一维数组来记录,方便查找 parants,所以将二维坐标用 node 函数转化为一维坐标。 """ defsolve(self, board: List[List[str]]) -> None: """ Do not return anything, modify board in-place instead. """ ifnot board: return m = len(board) n = len(board[0]) # 初始化并查集, 最后增加一个虚拟结点,用于比较 self.parent = [i for i inrange(m * n + 1)] self.count =0 for i inrange(m): for j inrange(n): self.parent[i * n + j] = i * n + j self.count += 1 # 用一个虚拟节点, 边界上的O 的父节点都是这个虚拟节点 dummy_node = m * n self.parent[dummy_node] = dummy_node
# 合并 dx = [-1, 1, 0, 0] dy = [0, 0, -1, 1] for i inrange(m): for j inrange(n): # 遇到O进行并查集操作合并 if board[i][j] == 'O': # 边界上的O,把它和dummy_node 合并成一个连通区域. if i == 0or i == m - 1or j == 0or j == n - 1: self._union(i * n + j, dummy_node) else: # 和上下左右合并成一个连通区域. for k inrange(len(dx)): x, y = i + dx[k], j + dy[k] if board[x][y] == 'O': self._union(i * n + j, x * n + y)
for i inrange(m): for j inrange(n): # 和dummy_node 在一个连通区域的,那么就是O if self._parent(i * n + j) == self._parent(dummy_node): board[i][j] = 'O' else: board[i][j] = 'X'
def_union(self, i, j): p1 = self._parent(i) p2 = self._parent(j) if p1 == p2: return self.parent[p1] = p2 self.count -= 1
def_parent(self, i): root = i while self.parent[root] != root: root = self.parent[root] # 路径压缩 while self.parent[i] != i: x = i i = self.parent[i] self.parent[x] = root return root