LC 547 (Template)


Solution to LeetCode 547 Friend Circles

LeetCode 547

Friend Circles (Median). [link]

1] DFS. Given a node, find the maximal connected components and mark all nodes in it as visited. Time complexity O(n^2). Space complexity O(n).

class Solution(object):
    def findCircleNum(self, isConnected):
        """
        :type isConnected: List[List[int]]
        :rtype: int
        """
        def DFS(C, cur, n):
            for i in range(n):
                if C[cur][i] == 1: # is friend
                    C[cur][i] = C[i][cur] = 0 # remove all friends in current friend group
                    DFS(C, i, n)
                    
        n = len(isConnected)
        count = 0
        for i in range(n):
            if isConnected[i][i] == 1: # is friend
                count += 1
                DFS(isConnected, i, n)
        return count

2] Union-Find- Set.

class UnionFind:
    def __init__(self):
        self.father = {}
        # count the number of sets
        self.num_of_sets = 0
    
    def find(self,x):
        root = x
        
        while self.father[root] != None:
            root = self.father[root]
        
        while x != root:
            original_father = self.father[x]
            self.father[x] = root
            x = original_father
        
        return root
    
    def merge(self,x,y):
        root_x,root_y = self.find(x),self.find(y)
        
        if root_x != root_y:
            self.father[root_x] = root_y
            self.num_of_sets -= 1
    
    def add(self,x):
        if x not in self.father:
            self.father[x] = None
            self.num_of_sets += 1

class Solution:
    def findCircleNum(self, M: List[List[int]]) -> int:
        uf = UnionFind()
        for i in range(len(M)):
            uf.add(i)
            for j in range(i):
                if M[i][j]:
                    uf.merge(i,j)
        
        return uf.num_of_sets

Template of Union-Find Set

class UnionFind:
    def __init__(self):
        self.father = {}
    
    def find(self,x):
        root = x

        while self.father[root] != None:
            root = self.father[root]

        # optimization: path compression O(log*n)
        while x != root:
            original_father = self.father[x]
            self.father[x] = root
            x = original_father
         
        return root
    
    def merge(self,x,y,val):
        root_x,root_y = self.find(x),self.find(y)
        
        if root_x != root_y:
            self.father[root_x] = root_y

    def is_connected(self,x,y):
        return self.find(x) == self.find(y)
    
    def add(self,x):
        if x not in self.father:
            self.father[x] = None

  TOC