Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
You are given an integer c representing c power stations, each with a unique identifier id from 1 to c (1‑based indexing).
These stations are interconnected via n bidirectional cables, represented by a 2D array connections, where each element connections[i] = [ui, vi] indicates a connection between station ui and station vi. Stations that are directly or indirectly connected form a power grid.
Initially, all stations are online (operational).
You are also given a 2D array queries, where each query is one of the following two types:
[1, x]: A maintenance check is requested for station x. If station x is online, it resolves the check by itself. If station x is offline, the check is resolved by the operational station with the smallest id in the same power grid as x. If no operational station exists in that grid, return -1.
[2, x]: Station x goes offline (i.e., it becomes non-operational).
Return an array of integers representing the results of each query of type [1, x] in the order they appear.
Note: The power grid preserves its structure; an offline (non‑operational) node remains part of its grid and taking it offline does not alter connectivity.
Example 1:
Input: c = 5, connections = [[1,2],[2,3],[3,4],[4,5]], queries = [[1,3],[2,1],[1,1],[2,2],[1,2]]
Output: [3,2,3]
Explanation:
{1, 2, 3, 4, 5} are online and form a single power grid.[1,3]: Station 3 is online, so the maintenance check is resolved by station 3.[2,1]: Station 1 goes offline. The remaining online stations are {2, 3, 4, 5}.[1,1]: Station 1 is offline, so the check is resolved by the operational station with the smallest id among {2, 3, 4, 5}, which is station 2.[2,2]: Station 2 goes offline. The remaining online stations are {3, 4, 5}.[1,2]: Station 2 is offline, so the check is resolved by the operational station with the smallest id among {3, 4, 5}, which is station 3.Example 2:
Input: c = 3, connections = [], queries = [[1,1],[2,1],[1,1]]
Output: [1,-1]
Explanation:
[1,1]: Station 1 is online in its isolated grid, so the maintenance check is resolved by station 1.[2,1]: Station 1 goes offline.[1,1]: Station 1 is offline and there are no other stations in its grid, so the result is -1.Constraints:
1 <= c <= 1050 <= n == connections.length <= min(105, c * (c - 1) / 2)connections[i].length == 21 <= ui, vi <= cui != vi1 <= queries.length <= 2 * 105queries[i].length == 2queries[i][0] is either 1 or 2.1 <= queries[i][1] <= cProblem summary: You are given an integer c representing c power stations, each with a unique identifier id from 1 to c (1‑based indexing). These stations are interconnected via n bidirectional cables, represented by a 2D array connections, where each element connections[i] = [ui, vi] indicates a connection between station ui and station vi. Stations that are directly or indirectly connected form a power grid. Initially, all stations are online (operational). You are also given a 2D array queries, where each query is one of the following two types: [1, x]: A maintenance check is requested for station x. If station x is online, it resolves the check by itself. If station x is offline, the check is resolved by the operational station with the smallest id in the same power grid as x. If no operational station exists in that grid, return -1. [2, x]: Station x goes offline (i.e., it becomes non-operational).
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Hash Map · Union-Find · Segment Tree
5 [[1,2],[2,3],[3,4],[4,5]] [[1,3],[2,1],[1,1],[2,2],[1,2]]
3 [] [[1,1],[2,1],[1,1]]
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3607: Power Grid Maintenance
class UnionFind {
private final int[] p;
private final int[] size;
public UnionFind(int n) {
p = new int[n];
size = new int[n];
for (int i = 0; i < n; ++i) {
p[i] = i;
size[i] = 1;
}
}
public int find(int x) {
if (p[x] != x) {
p[x] = find(p[x]);
}
return p[x];
}
public boolean union(int a, int b) {
int pa = find(a), pb = find(b);
if (pa == pb) {
return false;
}
if (size[pa] > size[pb]) {
p[pb] = pa;
size[pa] += size[pb];
} else {
p[pa] = pb;
size[pb] += size[pa];
}
return true;
}
}
class Solution {
public int[] processQueries(int c, int[][] connections, int[][] queries) {
UnionFind uf = new UnionFind(c + 1);
for (int[] e : connections) {
uf.union(e[0], e[1]);
}
TreeSet<Integer>[] st = new TreeSet[c + 1];
Arrays.setAll(st, k -> new TreeSet<>());
for (int i = 1; i <= c; i++) {
int root = uf.find(i);
st[root].add(i);
}
List<Integer> ans = new ArrayList<>();
for (int[] q : queries) {
int a = q[0], x = q[1];
int root = uf.find(x);
if (a == 1) {
if (st[root].contains(x)) {
ans.add(x);
} else if (!st[root].isEmpty()) {
ans.add(st[root].first());
} else {
ans.add(-1);
}
} else {
st[root].remove(x);
}
}
return ans.stream().mapToInt(Integer::intValue).toArray();
}
}
// Accepted solution for LeetCode #3607: Power Grid Maintenance
package main
import (
"container/heap"
"math"
"slices"
"sort"
)
// https://space.bilibili.com/206214
func processQueries1(c int, connections [][]int, queries [][]int) (ans []int) {
g := make([][]int, c+1)
for _, e := range connections {
x, y := e[0], e[1]
g[x] = append(g[x], y)
g[y] = append(g[y], x)
}
belong := make([]int, c+1)
for i := range belong {
belong[i] = -1
}
heaps := []hp{}
var h hp
var dfs func(int)
dfs = func(x int) {
belong[x] = len(heaps) // 记录节点 x 在哪个堆
h.IntSlice = append(h.IntSlice, x)
for _, y := range g[x] {
if belong[y] < 0 {
dfs(y)
}
}
}
for i := 1; i <= c; i++ {
if belong[i] >= 0 {
continue
}
h = hp{}
dfs(i)
heap.Init(&h)
heaps = append(heaps, h)
}
offline := make([]bool, c+1)
for _, q := range queries {
x := q[1]
if q[0] == 2 {
offline[x] = true
continue
}
if !offline[x] {
ans = append(ans, x)
continue
}
// 懒删除:取堆顶的时候,如果离线,才删除
h := &heaps[belong[x]]
for h.Len() > 0 && offline[h.IntSlice[0]] {
heap.Pop(h)
}
if h.Len() > 0 {
ans = append(ans, h.IntSlice[0])
} else {
ans = append(ans, -1)
}
}
return
}
type hp struct{ sort.IntSlice }
func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() any { a := h.IntSlice; v := a[len(a)-1]; h.IntSlice = a[:len(a)-1]; return v }
func processQueries(c int, connections [][]int, queries [][]int) []int {
g := make([][]int, c+1)
for _, e := range connections {
x, y := e[0], e[1]
g[x] = append(g[x], y)
g[y] = append(g[y], x)
}
belong := make([]int, c+1)
for i := range belong {
belong[i] = -1
}
cc := 0
var dfs func(int)
dfs = func(x int) {
belong[x] = cc
for _, y := range g[x] {
if belong[y] < 0 {
dfs(y)
}
}
}
for i := 1; i <= c; i++ {
if belong[i] < 0 {
dfs(i)
cc++
}
}
offlineTime := make([]int, c+1)
for i := range offlineTime {
offlineTime[i] = math.MaxInt
}
q1 := 0
for i, q := range slices.Backward(queries) {
if q[0] == 2 {
offlineTime[q[1]] = i // 记录最早离线时间
} else {
q1++
}
}
// 维护每个连通块的在线电站的最小编号
mn := make([]int, cc)
for i := range mn {
mn[i] = math.MaxInt
}
for i := 1; i <= c; i++ {
if offlineTime[i] == math.MaxInt { // 最终仍然在线
j := belong[i]
mn[j] = min(mn[j], i)
}
}
ans := make([]int, q1)
for i, q := range slices.Backward(queries) {
x := q[1]
j := belong[x]
if q[0] == 2 {
if offlineTime[x] == i { // 变回在线
mn[j] = min(mn[j], x)
}
} else {
q1--
if i < offlineTime[x] { // 已经在线(写 < 或者 <= 都可以)
ans[q1] = x
} else if mn[j] != math.MaxInt {
ans[q1] = mn[j]
} else {
ans[q1] = -1
}
}
}
return ans
}
# Accepted solution for LeetCode #3607: Power Grid Maintenance
class UnionFind:
def __init__(self, n):
self.p = list(range(n))
self.size = [1] * 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, a, b):
pa, pb = self.find(a), self.find(b)
if pa == pb:
return False
if self.size[pa] > self.size[pb]:
self.p[pb] = pa
self.size[pa] += self.size[pb]
else:
self.p[pa] = pb
self.size[pb] += self.size[pa]
return True
class Solution:
def processQueries(
self, c: int, connections: List[List[int]], queries: List[List[int]]
) -> List[int]:
uf = UnionFind(c + 1)
for u, v in connections:
uf.union(u, v)
st = [SortedList() for _ in range(c + 1)]
for i in range(1, c + 1):
st[uf.find(i)].add(i)
ans = []
for a, x in queries:
root = uf.find(x)
if a == 1:
if x in st[root]:
ans.append(x)
elif len(st[root]):
ans.append(st[root][0])
else:
ans.append(-1)
else:
st[root].discard(x)
return ans
// Accepted solution for LeetCode #3607: Power Grid Maintenance
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #3607: Power Grid Maintenance
// class UnionFind {
// private final int[] p;
// private final int[] size;
//
// public UnionFind(int n) {
// p = new int[n];
// size = new int[n];
// for (int i = 0; i < n; ++i) {
// p[i] = i;
// size[i] = 1;
// }
// }
//
// public int find(int x) {
// if (p[x] != x) {
// p[x] = find(p[x]);
// }
// return p[x];
// }
//
// public boolean union(int a, int b) {
// int pa = find(a), pb = find(b);
// if (pa == pb) {
// return false;
// }
// if (size[pa] > size[pb]) {
// p[pb] = pa;
// size[pa] += size[pb];
// } else {
// p[pa] = pb;
// size[pb] += size[pa];
// }
// return true;
// }
// }
//
// class Solution {
// public int[] processQueries(int c, int[][] connections, int[][] queries) {
// UnionFind uf = new UnionFind(c + 1);
// for (int[] e : connections) {
// uf.union(e[0], e[1]);
// }
//
// TreeSet<Integer>[] st = new TreeSet[c + 1];
// Arrays.setAll(st, k -> new TreeSet<>());
// for (int i = 1; i <= c; i++) {
// int root = uf.find(i);
// st[root].add(i);
// }
//
// List<Integer> ans = new ArrayList<>();
// for (int[] q : queries) {
// int a = q[0], x = q[1];
// int root = uf.find(x);
//
// if (a == 1) {
// if (st[root].contains(x)) {
// ans.add(x);
// } else if (!st[root].isEmpty()) {
// ans.add(st[root].first());
// } else {
// ans.add(-1);
// }
// } else {
// st[root].remove(x);
// }
// }
//
// return ans.stream().mapToInt(Integer::intValue).toArray();
// }
// }
// Accepted solution for LeetCode #3607: Power Grid Maintenance
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #3607: Power Grid Maintenance
// class UnionFind {
// private final int[] p;
// private final int[] size;
//
// public UnionFind(int n) {
// p = new int[n];
// size = new int[n];
// for (int i = 0; i < n; ++i) {
// p[i] = i;
// size[i] = 1;
// }
// }
//
// public int find(int x) {
// if (p[x] != x) {
// p[x] = find(p[x]);
// }
// return p[x];
// }
//
// public boolean union(int a, int b) {
// int pa = find(a), pb = find(b);
// if (pa == pb) {
// return false;
// }
// if (size[pa] > size[pb]) {
// p[pb] = pa;
// size[pa] += size[pb];
// } else {
// p[pa] = pb;
// size[pb] += size[pa];
// }
// return true;
// }
// }
//
// class Solution {
// public int[] processQueries(int c, int[][] connections, int[][] queries) {
// UnionFind uf = new UnionFind(c + 1);
// for (int[] e : connections) {
// uf.union(e[0], e[1]);
// }
//
// TreeSet<Integer>[] st = new TreeSet[c + 1];
// Arrays.setAll(st, k -> new TreeSet<>());
// for (int i = 1; i <= c; i++) {
// int root = uf.find(i);
// st[root].add(i);
// }
//
// List<Integer> ans = new ArrayList<>();
// for (int[] q : queries) {
// int a = q[0], x = q[1];
// int root = uf.find(x);
//
// if (a == 1) {
// if (st[root].contains(x)) {
// ans.add(x);
// } else if (!st[root].isEmpty()) {
// ans.add(st[root].first());
// } else {
// ans.add(-1);
// }
// } else {
// st[root].remove(x);
// }
// }
//
// return ans.stream().mapToInt(Integer::intValue).toArray();
// }
// }
Use this to step through a reusable interview workflow for this problem.
Track components with a list or adjacency matrix. Each union operation may need to update all n elements’ component labels, giving O(n) per union. For n union operations total: O(n²). Find is O(1) with direct lookup, but union dominates.
With path compression and union by rank, each find/union operation takes O(α(n)) amortized time, where α is the inverse Ackermann function — effectively constant. Space is O(n) for the parent and rank arrays. For m operations on n elements: O(m × α(n)) total.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.