↓Skip to main content
  1. LeetCode/

LeetCode 3607: Power Grid Maintenance

·3 mins· ·
LeetCode Medium Heap Union-Find Graph Lazy-Deletion
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-07-06

  • Submissions: Wrong Answer ×4 → Time Limit Exceeded ×10 → Accepted (15 total)

Approach
#

  1. The grid structure never changes: an offline station still belongs to its grid. So group stations once with Union-Find and never touch the groups again.
  2. A query asks for the smallest-id online station in the same group: keep one min-heap per group.
  3. Do not delete offline stations from the heap: on a query, pop the top while it is offline, until the top is online (lazy deletion).

Each station is popped at most once, so all queries together cost O((c + q) log c).

My Attempts
#

Wrong Answer ×4: a broken Union-Find
#

def union(self, x, y):
    root_x = self.find(x)
    root_y = self.find(y)
    if root_x == root_y:
        return
    if self.weight[x] >= self.weight[y]:
        self.parent[y] = self.parent[x]      # links x and y themselves, not their roots
    else:
        self.parent[x] = self.parent[y]
for ps in range(c):
    groups[uf.parent[ps] + 1].add(ps + 1)    # parent instead of find

Two problems:

  • After finding the roots, union links y under x’s parent. It links the nodes, not the roots, so the rest of y’s group stays under the old root.
  • Grouping used uf.parent[ps], but a parent is not necessarily a root. Use find.

The first attempt also had an off-by-one: groups were keyed by parent + 1, but queries looked up find(ps - 1) without the + 1.

Time Limit Exceeded ×10: taking the minimum of a whole group per query
#

After fixing Union-Find, the query looked like this:

remain = groups[uf.find(ps)] - off_line    # set difference over the whole group
res.append(min(remain))                    # then min over the whole group

Each query costs O(group size). Later attempts removed stations from the set when they went offline, switched to union by size, used an is_online array… but the query still called min(set), so it stayed O(c) and timed out when c and q were both large.

The problem was not Union-Find; it was the “query the minimum” step. It needs a structure that gives the minimum quickly and handles deletions: a heap with lazy deletion.

Solution
#

import heapq
from collections import defaultdict

class UF:
    def __init__(self, n: int):
        self.parent = list(range(n))

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

    def union(self, x: int, y: int) -> None:
        rx, ry = self.find(x), self.find(y)
        if rx != ry:
            self.parent[ry] = rx

class Solution:
    def processQueries(self, c: int, connections: List[List[int]], queries: List[List[int]]) -> List[int]:
        uf = UF(c + 1)
        for u, v in connections:
            uf.union(u, v)

        heaps = defaultdict(list)
        for station in range(1, c + 1):
            heaps[uf.find(station)].append(station)   # added in id order: already a valid heap

        online = [True] * (c + 1)
        res = []
        for op, x in queries:
            if op == 2:
                online[x] = False
            elif online[x]:
                res.append(x)
            else:
                heap = heaps[uf.find(x)]
                while heap and not online[heap[0]]:
                    heapq.heappop(heap)                # lazy deletion
                res.append(heap[0] if heap else -1)
        return res

Stations are added in increasing id order, so each list is already a valid min-heap and needs no heapify.

Complexity
#

Time O((c + n + q) log c), space O(c).

Mistakes to Avoid
#

  • A union that links the nodes instead of their roots.
  • Grouping with parent[x] instead of find(x).
  • Mixing 1-indexed and 0-indexed ids.
  • Tweaking data structure details while stuck on TLE, instead of asking what the query complexity is.

Interview Explanation
#

Going offline does not change the grid, so I group stations once with Union-Find and keep a min-heap of ids per group. Going offline only flips a flag in an online array; on a query, I pop the heap top while it is offline, until it is online or the heap is empty. Each station is popped at most once, so the total time is O((c + q) log c).

Related

LeetCode 3608: Minimum Time for K Connected Components
·2 mins
LeetCode Medium Union-Find Graph Sorting Binary-Search
LeetCode 3608 note: add edges back from the largest time; the time of the first edge that drops the component count below k is the answer
LeetCode 3493: Properties Graph
·2 mins
LeetCode Medium Graph Dfs Union-Find Hash-Map
LeetCode 3493 note: convert each row to a set, compare intersection sizes pairwise to add edges, then count components
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 721: Accounts Merge
·3 mins
LeetCode Medium Union-Find
LeetCode Problem Solving