classSolution(object): deffindCircleNum(self, isConnected): """ :type isConnected: List[List[int]] :rtype: int """ n = len(isConnected) # 模板應用,p 代表 parent (最根點) p = [i for i inrange(n)]
deffind(u): if p[u] == u: return u return find(p[u])
defunion(u, v): p[find(v)] = p[find(u)] # 開始 Union,避免環的產生故以大 union 小 for i inrange(n): for j inrange(i+1, n): if isConnected[i][j] == 1: union(i, j) # 確認 cluster 數量 cnt = 0 dic = {} for k in p: c = find(k) if c notin dic: dic[c] = 1 cnt += 1 return cnt
classSolution(object): deffindCircleNum(self, isConnected): """ :type isConnected: List[List[int]] :rtype: int """ n = len(isConnected)
vis = set() defdfs(i): q = deque() q.append(i) vis.add(i) while q: cur = q.popleft() for nxt inrange(n): if isConnected[cur][nxt] == 1: if nxt notin vis: vis.add(nxt) q.append(nxt) # 沒走過的點就 dfs 一次,且計算上一個 cluster cnt = 0 for i inrange(n): if i notin vis: vis.add(i) dfs(i) cnt += 1
return cnt
Numpy
思路
此解法為參考 aagrawal 大大的解法,利用線性代數之特性解之:將 Adjacency Matrix 視為 A 矩陣,求出其調和矩陣 L = D-A,其中 A 中的元件 (Components) 數量即是 L 的 nullspace,即 n-rank(L),此方法計算是 GPU-friendly 且更高效的。
程式
1 2 3 4 5 6 7 8 9 10 11 12 13
import numpy as np classSolution(object): deffindCircleNum(self, isConnected): """ :type isConnected: List[List[int]] :rtype: int """ n = len(isConnected) # L = D - A L = np.diag(np.sum(isConnected, axis=1)) - np.array(isConnected) rankL = np.linalg.matrix_rank(L)
return n - rankL
或者一行解:
1 2 3 4 5 6 7 8
import numpy as np classSolution(object): deffindCircleNum(self, isConnected): """ :type isConnected: List[List[int]] :rtype: int """ returnlen(isConnected) - np.linalg.matrix_rank(np.diag(np.sum(isConnected, axis=1)) - np.array(isConnected))
Complexity
Time Complexity: O(n^2)
因為 DFS 跟 Find & Union 都是一個點有可能經過 n 個連接點,且總共有 n 個點