↓Skip to main content
  1. LeetCode/

LeetCode 3493: Properties Graph

·2 mins· ·
LeetCode Medium Graph Dfs Union-Find Hash-Map
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: medium First Attempt: 2025-03-23

  • Submissions: Accepted (first try)

Approach
#

Rows i and j share an edge when their distinct numbers intersect in at least k values. Build the graph, then count connected components.

With n, m <= 100, comparing all O(n^2) pairs at O(m) each is about 10^6 operations, fast enough.

My Solution
#

class Solution:
    def numberOfComponents(self, properties: List[List[int]], k: int) -> int:
        n = len(properties)
        sets = [set(p) for p in properties]       # convert once, not on every comparison

        parent = list(range(n))

        def find(x: int) -> int:
            while parent[x] != x:
                parent[x] = parent[parent[x]]
                x = parent[x]
            return x

        components = n
        for i in range(n):
            for j in range(i + 1, n):
                if len(sets[i] & sets[j]) >= k:
                    ri, rj = find(i), find(j)
                    if ri != rj:
                        parent[ri] = rj
                        components -= 1
        return components

My original version built an adjacency list and counted components with a recursive DFS, with the same result. Two things could improve:

  • intersect(a, b) rebuilt set(a) and set(b) on every comparison, converting each row n times. Convert once and keep the sets.
  • graph[i] = graph.get(i, []) + [j] built a new list each time, slowing down as lists grew; append is enough.

This version uses Union-Find, merging while comparing, without an adjacency list.

Complexity
#

Time O(n^2 · m), space O(n · m).

Mistakes to Avoid
#

  • Intersecting the raw lists: deduplicate first, since the problem counts distinct numbers.
  • Rebuilding sets on every comparison.
  • Growing adjacency lists with list + [x].

Interview Explanation
#

I convert each row to a set, compare intersection sizes for every pair, and union the two rows with Union-Find when the size is at least k, decrementing the component count on each real merge. With n and m at most 100, the O(n^2 m) pairwise comparison is fast enough.

Related

LeetCode 133: Clone Graph
·1 min
LeetCode Medium Hash-Table Depth-First-Search Breadth-First-Search Graph
LeetCode 133 note: during DFS map each old node to its copy and return the existing copy when revisited, avoiding infinite recursion; an empty graph returns None
LeetCode 695: Max Area of Island
·2 mins
LeetCode Medium Array Depth-First-Search Breadth-First-Search Union-Find
LeetCode 695 note: DFS each unvisited 1 to measure its island and keep the maximum; cells are the integer 1, not a string
LeetCode 128: Longest Consecutive Sequence
·2 mins
LeetCode Medium Array Hash-Table Union-Find
LeetCode 128 note: put everything in a set and count upward only from values whose x - 1 is absent; each value is seen at most twice, O(n)
LeetCode 3494: Find the Minimum Amount of Time to Brew Potions
·2 mins
LeetCode Medium Simulation Prefix-Sum Array
LeetCode 3494 note: for each potion, push forward to get the last wizard’s finish time (everyone must be free), then subtract backward to get each wizard’s finish time
LeetCode 2487: Remove Nodes From Linked List
·1 min
LeetCode Medium Linked-List Stack Recursion Monotonic-Stack
LeetCode 2487 note: the kept nodes are non-increasing left to right; keep a monotonic stack, pop anything smaller than the new node, then link what remains
LeetCode 988: Smallest String Starting From Leaf
·1 min
LeetCode Medium String Backtracking Tree Depth-First-Search
LeetCode 988 note: DFS prepending each character so the string at a leaf already reads leaf to root, and keep the smallest