Python || union Find
IntuitionApproachComplexity
Time complexity:

Space complexity:
Code
# Intuition
<!-- Describe your first thoughts on how to solve this problem. -->

# Approach
<!-- Describe your approach to solving the problem. -->

# Complexity
- Time complexity:
<!-- Add your time complexity here, e.g. $$O(n)$$ -->

- Space complexity:
<!-- Add your space complexity here, e.g. $$O(n)$$ -->

# Code
```python3 []
class UnionFind:
    def __init__(self, size):
        self.parent = list(range(size))
        self.rank = [0] * size        

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

    def union(self, x, y):
        rootX = self.find(x)
        rootY = self.find(y)

        if rootX == rootY:
            return False

        if self.rank[rootX] < self.rank[rootY]:
            self.parent[rootX] = rootY
        elif self.rank[rootX] > self.rank[rootY]:
            self.parent[rootY] = rootX
        else:
            self.parent[rootY] = rootX
            self.rank[rootX] += 1

        return True


class Solution:
    def numberOfComponents(self, properties: List[List[int]], k: int) -> int:
        n, m = len(properties), len(properties[0])
        dp = [[0 for _ in range(n)] for _ in range(n)]

        def intersect(a, b):
            s = set(b)
            ans = 0
            for i in set(a):
                if i in s:
                    ans += 1
            return ans

            
        for i in range(n):
            for j in range(i + 1, n):
                dp[i][j] = True if k <= intersect(properties[i], properties[j]) else False

        uf = UnionFind(n)
        for i in range(n):
            for j in range(i + 1, n):
                if dp[i][j]:
                    uf.union(i, j)
        ans = 0
        for i, j in enumerate(uf.parent):
            if i == j:
                ans += 1
        return ans
```
['Array', 'Hash Table', 'Union Find', 'Graph', 'Python3']