leetcode笔记-union find并查集

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Sengo_GWU/article/details/83021550
        parents = range(n)
        rank = [0] * n

        def find(edge):
            if parents[edge] != edge:
                parents[edge] = find(parents[edge])
            return parents[edge]  
    
        def union(x, y):
            x, y = find(x), find(y)
            if x != y:
                if rank[x] >= rank[y]:
                    parents[y] = x
                    rank[x] += rank[x] == rank[y]
                else:
                    parents[x] = y

=======================================

Traveling is Fun

https://leetcode.com/discuss/interview-question/202553/Traveling-is-Fun/?goto=old

def connectedCities(n, g, originCities, destinationCities):
    n += 1
    parent = list(range(n))
    rank = [0] * n
    def find(x):
        if x != parent[x]:
            parent[x] = find(parent[x])
        return parent[x]
    def union(x, y):
        x, y = find(x), find(y)
        if x != y:
            if rank[x] >= rank[y]:
                parent[y] = x
                rank[x] += rank[x] == rank[y]
            else:
                parent[x] = y
    for i in range(g + 1, n):
        f = 2
        while i * f < n:
            union(i, i * f)
            f += 1
    return [int(find(s) == find(d)) for s, d in zip(originCities, destinationCities)]

947. Most Stones Removed with Same Row or Column

https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/solution/

Time Complexity: O(N \log N)O(NlogN), where NN is the length of stones. (If we used union-by-rank, this can be O(N * \alpha(N))O(N∗α(N)), where \alphaα is the Inverse-Ackermann function.)

class DSU:
    def __init__(self, N):
        self.p = range(N)

    def find(self, x):
        if self.p[x] != x:
            self.p[x] = self.find(self.p[x])
        return self.p[x]

    def union(self, x, y):
        xr = self.find(x)
        yr = self.find(y)
        self.p[xr] = yr

        
class Solution(object):
    def removeStones(self, stones):
        N = len(stones)
        dsu = DSU(20000)
        for x, y in stones:
            dsu.union(x, y + 10000)
        
        return N - len({dsu.find(x) for x, y in stones})

 

305. Number of Islands II

不用Union by rank 也能通过 

class Solution(object):
    def numIslands2(self, m, n, positions):
        """
        :type m: int
        :type n: int
        :type positions: List[List[int]]
        :rtype: List[int]
        """
        parent, rank = {}, {}
        
        def find(x):
            if parent[x] != x:
                parent[x] = find(parent[x])  # path compression
            return parent[x]
        
        def union(x, y):
            p1, p2 = find(x), find(y)
            if p1 == p2:
                return 0
            else:  # union by rank
                if rank[p1] < rank[p2]:
                    parent[p1] = p2
                else:
                    parent[p2] = p1
                    if rank[p1] == rank[p2]:
                        rank[p1] += 1
            return 1
                
        res, count = [], 0
        for i, j in positions:
            x = i, j
            parent[x] = x
            rank[x] = 0
            count += 1
            for y in (i+1, j), (i-1, j), (i, j+1), (i, j-1):
                if y in parent:
                    count -= union(x, y)
            res.append(count)
            
        return res

323. Number of Connected Components in an Undirected Graph

class Solution(object):
    def countComponents(self, n, edges):
        
        parents = range(n)
        
        def find(a):
            if parents[a] != a:
                return find(parents[a])
            return a
        
        def union(b, p1):
            while True:
                p = parents[b]
                parents[b] = p1
                if p != b:
                    b = p
                else:
                    break
            
        for a, b in edges:
            p1, p2 = find(a), find(b)
            if p1 != p2:
                union(b, p1)
        return len({find(x) for x in xrange(n)})
                

721. Accounts Merge

class Solution(object):
    def init(self, accounts):
        self.parents = {}
        self.owner = {}
        
        for acc in accounts:
            owner = acc[0]
            root = acc[1]  # 第一个邮箱为root, root的特点是指向自己
            self.owner[root] = owner
            for email in acc[1:]:
                if email not in self.parents:
                    self.parents[email] = root
                else:
                    self.union(root, self.parents[email])
    
    def find(self, x):
        if self.parents[x] == x:
            return x
        
        self.parents[x] = self.find(self.parents[x])
        return self.parents[x]
    
    def union(self, x, y):
        px = self.find(x)
        py = self.find(y)
        self.parents[py] = px
                
    def accountsMerge(self, accounts):
        """
        :type accounts: List[List[str]]
        :rtype: List[List[str]]
        """
        self.init(accounts)
        for acc in accounts:  
            for email in acc[1:]:
                self.find(email)  # 每次find都会把所有上面的节点指向root
        
        groups = list(set(self.parents.values()))  # values的值是父节点
        res = []
        for j in xrange(len(groups)):
            temp = []
            for key in self.parents:
                if self.parents[key] == groups[j]:
                    temp.append(key)
            temp = sorted(temp)
            temp.insert(0, self.owner[groups[j]])
            res.append(temp)
        return res

下面的TLE?? 

class Solution(object):
    def accountsMerge(self, accounts):
        parent = {}
        owner = {}
        
        def find(email):
            if parent[email] != email:
                parent[email] = find(parent[email])
            return parent[email]            
        
        def union(e1, e2):
            p1 = parent[e1]
            p2 = parent[e2]
            parent[p2] = p1 

        for acc in accounts:
            name = acc[0]
            root = acc[1]
            owner[root] = name
            for e in acc[1:]:
                if e not in parent:
                    parent[e] = root
                else:
                    union(root, parent[e])

        for e in parent:
            find(e)
        
        roots = list(set(parent.values()))
        re = []
        for root in roots:
            temp = []
            for e in parent:
                if parent[e] == root:
                    temp.append(e)
            temp.sort()
            temp.insert(0, owner[root])
            re.append(temp)
        return re

261. Graph Valid Tree

class Solution(object):
    def validTree(self, n, edges):
        """
        :type n: int
        :type edges: List[List[int]]
        :rtype: bool
        """
        parents = range(n)
        
        def find(b):  # 找到root parent
            if parents[b] != b:
                return find(parents[b])
            return b
        
        def union(b, p1):  # 把b和b的所有parent 的parent设为p1
            while True:
                p = parents[b]
                parents[b] = p1
                if p != b:
                    b = p
                else:
                    break
        
        for a, b in edges:  # 如果edge a, b have the same root parent, then circle, else union
            p1 = find(a)
            p2 = find(b)
            
            if p1 == p2:
                return False  # circle 
            else:  
                union(b, p1)  # union
        
        for i in xrange(n):  # check if all the node have the same root parent, if not,there exist more than 1 tree
            if i == 0:
                p = find(i)
            else:
                print i, find(i)
                if find(i) != p:
                    return False
        return True
            
            
            

猜你喜欢

转载自blog.csdn.net/Sengo_GWU/article/details/83021550