def numIslands(self, grid: List[List[str]]) -> int: if not grid or not len(grid) or not len(grid[0]): return 0 R = len(grid) C = len(grid[0]) cnt = 0 for i in range(R): for j in range(C): if grid[i][j] == '1': cnt += 1 # Special: uf.count (number of '1's is not equal to len(self.parents) in this case uf = UF(R * C, cnt) def getFlatIdx(i, j): return C * i + j directions = [[1, 0], [0, 1]] for i in range(R): for j in range(C): if grid[i][j] == '1': for d in directions: ii, jj = i + d[0], j + d[1] if ii < R and jj < C and grid[ii][jj] == '1': u, v = getFlatIdx(i, j), getFlatIdx(ii, jj) # print((i,j), (ii,jj), u, v) uf.union(u, v) # print(uf.count) return uf.count
def numIslands2(self, m: int, n: int, positions: List[List[int]]) -> List[int]: grid = [[0 for _ in range(n)] for _ in range(m)] uf = UF(m * n, 0) def getFlatIdx(i, j): return n * i + j directions = [[1, 0], [-1, 0], [0, 1], [0, -1]] res = [] input_set = set() for pos in positions: # edge case - dedupe x, y = pos[0], pos[1] if (x,y) in input_set: res.append(uf.count) continue input_set.add((x,y)) grid[x][y] = 1 uf.count += 1 for direction in directions: u = x + direction[0] v = y + direction[1] if 0 <= u < m and 0 <= v < n and grid[u][v] == 1: uf.union(getFlatIdx(x, y), getFlatIdx(u, v)) res.append(uf.count) print(res) return res
def findRedundantConnection(self, edges: List[List[int]]) -> List[int]: N = len(edges) uf = UF(N) for edge in edges: if not uf.union(edge[0] - 1, edge[1] - 1): print(edge) return edge return []
def minSwapsCouples(self, row: List[int]) -> int: N = len(row) // 2 # floor division uf = UF(N) for i in range(N): a, b = row[2 * i], row[2 * i + 1] uf.union(a // 2, b // 2) res = N - uf.count print(res) return res
def findCircleNum(self, M: List[List[int]]) -> int: N = len(M) uf = UF(N) for i in range(N): for j in range(i + 1, N): if M[i][j]: # merge as many direct friends as possible into clusters uf.union(i, j) # how many root nodes after unions clusters = set() for i in range(N): clusters.add(uf.find(i)) size = len(clusters) print(size) return size
def longestConsecutive(self, nums: List[int]) -> int: N = len(nums) uf = UF(N) hashmap: Dict[int, int] = dict() directions = [1, -1] for i, num in enumerate(nums): # edge case - dedupe duplicate elements if num in hashmap: continue hashmap[num] = i # if consecutive number is also in hashmap, union as an edge for direction in directions: if num + direction in hashmap: uf.union(i, hashmap[num + direction]) res = uf.maxUnion() print(res) return res
def areSentencesSimilarTwo(self, words1: List[str], words2: List[str], pairs: List[List[str]]) -> bool: global_incr = 0 def getWordIdx(word: str, dictionary: Dict[str, int], create: bool = False) -> int: nonlocal global_incr if word in dictionary: return dictionary[word] elif create: dictionary[word] = global_incr global_incr += 1 return dictionary[word] return -1 if len(words1) != len(words2): return False N = len(pairs) * 2 uf = UF(N) # use a word-to-index map to map all words to UnionFind's int data structure (starting from 0!) hashmap = dict() # build union-find forest from all similar pairs, similar words will compose a cycle inside for edge in pairs: u = getWordIdx(edge[0], hashmap, True) v = getWordIdx(edge[1], hashmap, True) uf.union(u, v) # compare each word in words1 and words2 to see whether they are similar for i, w1 in enumerate(words1): w2 = words2[i] if w1 == w2: continue u, v = getWordIdx(w1, hashmap), getWordIdx(w2, hashmap) if u < 0 or v < 0: return False if uf.find(u) != uf.find(v): return False return True
def __init__(self, n: int): UF.__init__(self, n) self.parents = [-1] * n self.weights = [1.0] * n