3607. Power Grid Maintenance
Problem Description
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 connected by n bidirectional cables, given as a 2D array connections, where each connections[i] = [u_i, v_i] means there is a cable between station u_i and station v_i. Any group of stations that are directly or indirectly connected forms a power grid.
At the start, all stations are online (operational).
You are also given a 2D array queries, where each query is one of two types:
[1, x]: A maintenance check is requested for stationx.- If station
xis online, it handles the check by itself, so the answer isx. - If station
xis offline, the check is handled by the operational station with the smallestidthat belongs to the same power grid asx. - If there is no operational station in that grid, the answer is
-1.
- If station
[2, x]: Stationxgoes offline (it becomes non-operational).
You must return an array of integers containing the results of every query of type [1, x], in the order they appear.
Note: Taking a station offline does not change the structure of the grid. An offline station stays part of its grid, and connectivity between stations is never affected by a station going offline.
How We Pick the Algorithm
Why Disjoint Set Union?
This problem maps to Disjoint Set Union through a short path in the full flowchart.
The problem groups stations into power grids using Union-Find, then maintains a sorted set of online stations per grid to answer maintenance and offline queries.
Open in FlowchartShow step-by-step reasoning
First, let's pin down the algorithm using the Flowchart. Here's a step-by-step walkthrough:
Is it a graph?
- Yes: The power stations are nodes, and the cables connecting them are edges. Groups of connected stations form power grids, which are essentially connected components in a graph.
Is it a tree?
- No: The grid can contain cycles (multiple cables forming loops), and there is no guarantee of a single connected acyclic structure. We have a general graph with possibly many components.
Is the problem related to directed acyclic graphs?
- No: The cables are bidirectional, so the graph is undirected, not directed.
Is the problem related to shortest paths?
- No: We never measure distances or path lengths between stations. We only care about which stations belong to the same grid.
Does the problem involve connectivity?
- Yes: The core of the problem is determining which stations are "directly or indirectly connected" into the same power grid, then querying within those connected groups.
Disjoint Set Union?
- Yes: Connectivity between components is naturally handled by grouping stations into sets. We can traverse each component using Depth-First Search to label all stations belonging to the same grid, then maintain a sorted structure of online stations per grid to answer the queries.
Conclusion: The flowchart guides us toward a connectivity-based approach. Using Depth-First Search to identify the connected components (power grids), combined with a sorted set per grid to track online stations, lets us efficiently resolve each maintenance check and offline query.
Intuition
The key observation is that taking a station offline never changes the structure of the grid. The connections are fixed from the start, and an offline station still belongs to its power grid. This means the grouping of stations into grids is decided entirely by the connections and stays constant throughout all the queries.
So the first thing we want to know is: which stations belong to the same grid? Since two stations are in the same grid if they are directly or indirectly connected, this is simply a matter of finding connected components. We can build these groups once at the beginning, either by running a Depth-First Search from each unvisited station, or by using a Union-Find structure to merge connected stations into the same set. Every station then maps to a representative (the root) that identifies its grid.
Now look at what each query actually needs:
- For
[1, x], ifxis online we just answerx. Otherwise we need the smallestidamong the online stations in the same grid asx, or-1if none remain online. - For
[2, x], we mark stationxas offline, which means it should no longer be considered when looking for the smallest online station.
This tells us that for each grid we must be able to do two things efficiently: remove a station (when it goes offline) and find the smallest remaining station (when answering a check). A plain list would be slow, but a sorted set fits perfectly. With a sorted set per grid, deletion and finding the minimum are both fast.
Putting it together: we group all stations by grid once at the start, place each station's id into the sorted set of its grid, then process the queries in order. For a check, we find the grid root of x and either return x (if still present) or the first element of that grid's sorted set (or -1 if it's empty). For an offline operation, we simply discard x from its grid's sorted set. Because the grid structure is fixed, we only ever pay for the lightweight set operations during the queries.
Pattern Learn more about Depth-First Search, Breadth-First Search, Union Find, Graph and Heap (Priority Queue) patterns.
Solution Approach
Solution 1: Union-Find + Sorted Set
We use Union-Find to maintain the connection relationships between power stations, which lets us determine the grid each station belongs to. For each grid, we keep a sorted set (such as SortedList in Python, TreeSet in Java, or std::set in C++) holding all online station IDs in that grid, so we can efficiently query and delete stations.
The specific steps are as follows:
-
Initialize the Union-Find structure over
c + 1slots (using 1-based indexing) and process all connection relationships, merging connected stations into the same set. In the code,uf.union(u, v)merges the sets ofuandv, anduf.find(x)returns the root representing the grid of stationx. The union step uses union by size to keep the tree shallow, andfinduses path compression for speed. -
Create a sorted set for each grid. We loop over every station
ifrom1toc, find its grid root withuf.find(i), and addito the sorted setst[root]. After this, each grid's sorted set contains all of its station IDs in ascending order. -
Iterate through the query list. For each query
[a, x], first computeroot = uf.find(x):- For a query
[1, x](a == 1):- If
xis still online (x in st[root]), appendxto the answer. - Otherwise, if the set is non-empty (
len(st[root])), append the smallest online stationst[root][0]. - Otherwise, append
-1since no operational station remains in the grid.
- If
- For a query
[2, x](a == 2), callst[root].discard(x)to remove stationxfrom its grid's sorted set, marking it offline.
- For a query
-
Finally, return all query results collected for type
[1, x]queries.
Because the grid membership never changes, the heavy work of grouping is done once up front. Each query then costs only O(log m) time for the membership check, minimum lookup, or deletion on a sorted set of size m. The overall time complexity is O((c + n + q) * log c), where c is the number of stations, n is the number of connections, and q is the number of queries. The space complexity is O(c) for the Union-Find arrays and the sorted sets combined.
Example Walkthrough
Let's trace through a small example to see how the Union-Find + Sorted Set approach works.
Input:
c = 5(stations with ids1, 2, 3, 4, 5)connections = [[1, 2], [2, 3], [4, 5]]queries = [[1, 3], [2, 1], [1, 3], [2, 2], [1, 3], [1, 4], [2, 4], [1, 4], [2, 5], [1, 4]]
Step 1 & 2: Build the grids and sorted sets
First, we run Union-Find over the connections to discover the connected components (grids):
union(1, 2)→{1, 2}are linkedunion(2, 3)→{1, 2, 3}are linkedunion(4, 5)→{4, 5}are linked
This produces two grids. Suppose find returns root 1 for the first grid and root 4 for the second. We then place each station into its grid's sorted set:
| Grid root | Sorted set of online stations |
|---|---|
1 | [1, 2, 3] |
4 | [4, 5] |
Station 5 is never queried, but it still belongs to grid 4.
Step 3: Process the queries in order
We keep an answer list ans for every [1, x] query.
| Query | Action | Grid set state | Answer |
|---|---|---|---|
[1, 3] | root=1, station 3 is online (3 in {1,2,3}) → answer 3 | {1,2,3}, {4,5} | 3 |
[2, 1] | root=1, discard 1 | {2,3}, {4,5} | — |
[1, 3] | root=1, station 3 is online → answer 3 | {2,3}, {4,5} | 3 |
[2, 2] | root=1, discard 2 | {3}, {4,5} | — |
[1, 3] | root=1, station 3 is online → answer 3 | {3}, {4,5} | 3 |
[1, 4] | root=4, station 4 is online → answer 4 | {3}, {4,5} | 4 |
[2, 4] | root=4, discard 4 | {3}, {5} | — |
[1, 4] | root=4, station 4 is offline; set {5} non-empty → smallest 5 | {3}, {5} | 5 |
[2, 5] | root=4, discard 5 | {3}, {} | — |
[1, 4] | root=4, station 4 offline; set {} empty → no station → -1 | {3}, {} | -1 |
Final Result
Collecting answers from each [1, x] query in order:
[3, 3, 3, 4, 5, -1]
Key Takeaways from the Trace
- The grid grouping (
{1,2,3}and{4,5}) was computed once and never changed, even as stations went offline. - A
[2, x]query only removesxfrom its grid's sorted set — it does not split the grid or alter connectivity. - For a
[1, x]query, ifxis still in its set we answerxdirectly; otherwise we take the smallest remaining id (st[root][0]), and fall back to-1only when the grid has no online stations left (as seen in the last query).
Solution Implementation
1from typing import List
2from sortedcontainers import SortedList
3
4
5class UnionFind:
6 def __init__(self, n: int) -> None:
7 # parent[i] is the parent of node i; initially each node is its own parent
8 self.parent = list(range(n))
9 # size[i] is the number of nodes in the tree rooted at i (used for union by size)
10 self.size = [1] * n
11
12 def find(self, x: int) -> int:
13 # Find the root of x with path compression
14 if self.parent[x] != x:
15 self.parent[x] = self.find(self.parent[x])
16 return self.parent[x]
17
18 def union(self, a: int, b: int) -> bool:
19 # Merge the sets containing a and b; return False if already connected
20 root_a, root_b = self.find(a), self.find(b)
21 if root_a == root_b:
22 return False
23 # Union by size: attach the smaller tree under the larger tree
24 if self.size[root_a] > self.size[root_b]:
25 self.parent[root_b] = root_a
26 self.size[root_a] += self.size[root_b]
27 else:
28 self.parent[root_a] = root_b
29 self.size[root_b] += self.size[root_a]
30 return True
31
32
33class Solution:
34 def processQueries(
35 self, c: int, connections: List[List[int]], queries: List[List[int]]
36 ) -> List[int]:
37 # Build the union-find structure for stations numbered 1..c
38 uf = UnionFind(c + 1)
39 for u, v in connections:
40 uf.union(u, v)
41
42 # For each component root, keep a sorted list of its online stations
43 online_by_root = [SortedList() for _ in range(c + 1)]
44 for station in range(1, c + 1):
45 online_by_root[uf.find(station)].add(station)
46
47 ans: List[int] = []
48 for query_type, station in queries:
49 root = uf.find(station)
50 if query_type == 1:
51 # Maintenance check on the given station
52 if station in online_by_root[root]:
53 # The station itself is online, so it can serve
54 ans.append(station)
55 elif online_by_root[root]:
56 # Otherwise return the smallest online station in the component
57 ans.append(online_by_root[root][0])
58 else:
59 # No online station available in the component
60 ans.append(-1)
61 else:
62 # Take the given station offline by removing it from its component
63 online_by_root[root].discard(station)
64
65 return ans
661class UnionFind {
2 // Parent array: p[i] stores the parent of node i
3 private final int[] p;
4 // Size array: size[i] stores the size of the tree rooted at i
5 private final int[] size;
6
7 public UnionFind(int n) {
8 p = new int[n];
9 size = new int[n];
10 // Initially every node is its own root with size 1
11 for (int i = 0; i < n; ++i) {
12 p[i] = i;
13 size[i] = 1;
14 }
15 }
16
17 /**
18 * Finds the root of node x with path compression.
19 *
20 * @param x the node to query
21 * @return the root representative of the set containing x
22 */
23 public int find(int x) {
24 if (p[x] != x) {
25 // Path compression: point x directly to the root
26 p[x] = find(p[x]);
27 }
28 return p[x];
29 }
30
31 /**
32 * Merges the sets containing a and b using union by size.
33 *
34 * @param a the first node
35 * @param b the second node
36 * @return true if a merge happened, false if they were already connected
37 */
38 public boolean union(int a, int b) {
39 int pa = find(a), pb = find(b);
40 // Already in the same set, no merge needed
41 if (pa == pb) {
42 return false;
43 }
44 // Attach the smaller tree under the larger one
45 if (size[pa] > size[pb]) {
46 p[pb] = pa;
47 size[pa] += size[pb];
48 } else {
49 p[pa] = pb;
50 size[pb] += size[pa];
51 }
52 return true;
53 }
54}
55
56class Solution {
57 public int[] processQueries(int c, int[][] connections, int[][] queries) {
58 // Build the disjoint set over nodes 1..c (index 0 unused)
59 UnionFind uf = new UnionFind(c + 1);
60 for (int[] e : connections) {
61 uf.union(e[0], e[1]);
62 }
63
64 // For each connected component (keyed by its root), maintain an
65 // ordered set of currently online nodes so we can quickly fetch
66 // the smallest available node.
67 TreeSet<Integer>[] st = new TreeSet[c + 1];
68 Arrays.setAll(st, k -> new TreeSet<>());
69 for (int i = 1; i <= c; i++) {
70 int root = uf.find(i);
71 st[root].add(i);
72 }
73
74 List<Integer> ans = new ArrayList<>();
75 for (int[] q : queries) {
76 int a = q[0], x = q[1];
77 // Identify the component that node x belongs to
78 int root = uf.find(x);
79
80 if (a == 1) {
81 // Type 1 query: report a usable node in x's component
82 if (st[root].contains(x)) {
83 // x itself is online, prefer returning x
84 ans.add(x);
85 } else if (!st[root].isEmpty()) {
86 // Otherwise return the smallest online node in the component
87 ans.add(st[root].first());
88 } else {
89 // No online node available in the component
90 ans.add(-1);
91 }
92 } else {
93 // Type 2 query: take node x offline
94 st[root].remove(x);
95 }
96 }
97
98 // Convert the result list to a primitive int array
99 return ans.stream().mapToInt(Integer::intValue).toArray();
100 }
101}
1021class UnionFind {
2public:
3 // Initialize the union-find structure with n elements (indices 0..n-1).
4 UnionFind(int n) {
5 parent = vector<int>(n);
6 componentSize = vector<int>(n, 1);
7 // Each element starts as its own root: parent[i] = i.
8 iota(parent.begin(), parent.end(), 0);
9 }
10
11 // Merge the sets containing a and b.
12 // Returns false if they already belong to the same set, true otherwise.
13 bool unite(int a, int b) {
14 int rootA = find(a), rootB = find(b);
15 if (rootA == rootB) {
16 return false;
17 }
18 // Union by size: attach the smaller tree under the larger one.
19 if (componentSize[rootA] > componentSize[rootB]) {
20 parent[rootB] = rootA;
21 componentSize[rootA] += componentSize[rootB];
22 } else {
23 parent[rootA] = rootB;
24 componentSize[rootB] += componentSize[rootA];
25 }
26 return true;
27 }
28
29 // Find the root representative of x with path compression.
30 int find(int x) {
31 if (parent[x] != x) {
32 parent[x] = find(parent[x]);
33 }
34 return parent[x];
35 }
36
37private:
38 vector<int> parent; // parent[i] points to the parent of node i
39 vector<int> componentSize; // componentSize[root] holds the size of the component
40};
41
42class Solution {
43public:
44 vector<int> processQueries(int c, vector<vector<int>>& connections, vector<vector<int>>& queries) {
45 // Build the connected components from the given connections.
46 // Use indices 1..c, so allocate c + 1 slots.
47 UnionFind uf(c + 1);
48 for (auto& edge : connections) {
49 uf.unite(edge[0], edge[1]);
50 }
51
52 // For each component root, store its online stations in a sorted set,
53 // so the smallest available station can be retrieved quickly.
54 vector<set<int>> componentStations(c + 1);
55 for (int i = 1; i <= c; i++) {
56 componentStations[uf.find(i)].insert(i);
57 }
58
59 vector<int> ans;
60 for (auto& query : queries) {
61 int type = query[0], station = query[1];
62 int root = uf.find(station);
63 if (type == 1) {
64 // Type 1: query the maintenance station for the given station.
65 if (componentStations[root].count(station)) {
66 // The station itself is online; answer with it.
67 ans.push_back(station);
68 } else if (!componentStations[root].empty()) {
69 // Otherwise return the smallest online station in the component.
70 ans.push_back(*componentStations[root].begin());
71 } else {
72 // No online station available in this component.
73 ans.push_back(-1);
74 }
75 } else {
76 // Type 2: take the station offline by removing it from its component.
77 componentStations[root].erase(station);
78 }
79 }
80 return ans;
81 }
82};
831// Global union-find arrays.
2let parent: number[] = []; // parent[i] points to the parent of node i
3let componentSize: number[] = []; // componentSize[root] holds the size of the component
4
5// Initialize the union-find structure with n elements (indices 0..n-1).
6function init(n: number): void {
7 parent = new Array(n);
8 componentSize = new Array(n).fill(1);
9 // Each element starts as its own root: parent[i] = i.
10 for (let i = 0; i < n; i++) {
11 parent[i] = i;
12 }
13}
14
15// Find the root representative of x with path compression.
16function find(x: number): number {
17 if (parent[x] !== x) {
18 parent[x] = find(parent[x]);
19 }
20 return parent[x];
21}
22
23// Merge the sets containing a and b.
24// Returns false if they already belong to the same set, true otherwise.
25function unite(a: number, b: number): boolean {
26 const rootA = find(a);
27 const rootB = find(b);
28 if (rootA === rootB) {
29 return false;
30 }
31 // Union by size: attach the smaller tree under the larger one.
32 if (componentSize[rootA] > componentSize[rootB]) {
33 parent[rootB] = rootA;
34 componentSize[rootA] += componentSize[rootB];
35 } else {
36 parent[rootA] = rootB;
37 componentSize[rootB] += componentSize[rootA];
38 }
39 return true;
40}
41
42// A simple binary min-heap of numbers, used to emulate C++'s ordered set
43// for quickly retrieving the smallest online station in a component.
44class MinHeap {
45 private data: number[] = [];
46
47 // Push a value into the heap, sifting it up to its correct position.
48 push(value: number): void {
49 this.data.push(value);
50 let i = this.data.length - 1;
51 while (i > 0) {
52 const parentIdx = (i - 1) >> 1;
53 if (this.data[parentIdx] <= this.data[i]) {
54 break;
55 }
56 [this.data[parentIdx], this.data[i]] = [this.data[i], this.data[parentIdx]];
57 i = parentIdx;
58 }
59 }
60
61 // Return the smallest value without removing it.
62 top(): number {
63 return this.data[0];
64 }
65
66 // Remove and return the smallest value, sifting the last element down.
67 pop(): number {
68 const top = this.data[0];
69 const last = this.data.pop()!;
70 if (this.data.length > 0) {
71 this.data[0] = last;
72 let i = 0;
73 const n = this.data.length;
74 while (true) {
75 const left = 2 * i + 1;
76 const right = 2 * i + 2;
77 let smallest = i;
78 if (left < n && this.data[left] < this.data[smallest]) {
79 smallest = left;
80 }
81 if (right < n && this.data[right] < this.data[smallest]) {
82 smallest = right;
83 }
84 if (smallest === i) {
85 break;
86 }
87 [this.data[i], this.data[smallest]] = [this.data[smallest], this.data[i]];
88 i = smallest;
89 }
90 }
91 return top;
92 }
93
94 // Whether the heap currently holds no elements.
95 empty(): boolean {
96 return this.data.length === 0;
97 }
98}
99
100function processQueries(c: number, connections: number[][], queries: number[][]): number[] {
101 // Build the connected components from the given connections.
102 // Use indices 1..c, so allocate c + 1 slots.
103 init(c + 1);
104 for (const edge of connections) {
105 unite(edge[0], edge[1]);
106 }
107
108 // For each component root, store its online stations in a min-heap,
109 // so the smallest available station can be retrieved quickly.
110 const componentStations: MinHeap[] = new Array(c + 1);
111 for (let i = 0; i <= c; i++) {
112 componentStations[i] = new MinHeap();
113 }
114 // Track whether each station is currently online (not taken offline).
115 const online: boolean[] = new Array(c + 1).fill(true);
116
117 for (let i = 1; i <= c; i++) {
118 componentStations[find(i)].push(i);
119 }
120
121 const ans: number[] = [];
122 for (const query of queries) {
123 const type = query[0];
124 const station = query[1];
125 const root = find(station);
126 if (type === 1) {
127 // Type 1: query the maintenance station for the given station.
128 if (online[station]) {
129 // The station itself is online; answer with it.
130 ans.push(station);
131 } else {
132 // Otherwise return the smallest online station in the component,
133 // lazily discarding heap tops that are already offline.
134 const heap = componentStations[root];
135 while (!heap.empty() && !online[heap.top()]) {
136 heap.pop();
137 }
138 if (!heap.empty()) {
139 ans.push(heap.top());
140 } else {
141 // No online station available in this component.
142 ans.push(-1);
143 }
144 }
145 } else {
146 // Type 2: take the station offline by marking it offline.
147 online[station] = false;
148 }
149 }
150 return ans;
151}
152Time and Space Complexity
-
Time Complexity:
O((c + n + q) × log c), wherecis the number of stations, andnandqare the number of connections and queries, respectively.- Building the Union-Find and processing all
nconnections viauniontakesO(n × α(c)), which is effectivelyO(n)(or bounded byO(n × log c)). - Distributing the
cstations into theSortedListstructures requirescinsertions, each costingO(log c), givingO(c × log c). - Processing the
qqueries: each query performs afind, plus either a membership check / first-element access (in,st[root][0]) or adiscardon aSortedList, each operation costingO(log c). This results inO(q × log c). - Combining these terms yields
O((c + n + q) × log c).
- Building the Union-Find and processing all
-
Space Complexity:
O(c), wherecis the number of stations.- The Union-Find arrays
pandsizeeach useO(c)space. - The list of
SortedListstructures collectively stores allcstations, usingO(c)space in total. - Therefore, the overall space complexity is
O(c).
- The Union-Find arrays
Pattern Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Using find(x) to Get the Root After the Stations Are Already Grouped, but Indexing the Sorted Set by the Wrong Root
A subtle and very common bug is mismatching the root used to populate the sorted sets with the root used to query them. Because union uses union-by-size, the final root of a component is not necessarily the smallest id, the first id, or any predictable value — it is whatever node ends up at the top of the tree.
If you build the sorted sets like this:
# WRONG: grouping by node id or a stale root online_by_root[station].add(station) # bug: uses the station itself, not its root
but later query with uf.find(station), the lookups will land on empty or incorrect sets and produce wrong answers (often -1 for grids that actually have online stations).
Solution: Always key the sorted sets by the canonical root returned by find, both when filling them and when querying them. The code does this correctly:
for station in range(1, c + 1):
online_by_root[uf.find(station)].add(station) # fill by root
...
root = uf.find(station) # query by the same root
Since find applies path compression, the root returned during the query phase is stable and consistent with the fill phase.
Pitfall 2: Forgetting That Path Compression Can Change parent, but Never the Root
Some implementations cache uf.find(station) once and reuse it across many queries, assuming the root might shift. With this Union-Find, all unions happen before any query, so each component's root is fixed for the entire query phase. The danger is the opposite: re-deriving the root incorrectly. As long as no union is called during the query loop (and none is here), uf.find(x) is guaranteed to return the same root every time, so caching is safe — but only because the structure is frozen.
Solution: Keep all union calls strictly in the preprocessing phase. If the problem were ever extended to add edges between queries, the precomputed online_by_root lists keyed by root would become invalid, and you'd need a different design (e.g., merging sorted sets on union, smaller-to-larger).
Pitfall 3: Off-by-One Errors With 1-Based Indexing
Stations are numbered 1..c, but the arrays are sized and looped over carelessly in many attempts:
uf = UnionFind(c) # WRONG: index c is unreachable, station c overflows
online_by_root = [SortedList() for _ in range(c)] # WRONG: too small
Because stations use ids up to c, you must allocate c + 1 slots and reserve index 0 as unused.
Solution: Size every structure as c + 1 and iterate range(1, c + 1), exactly as the code does. Index 0 is simply ignored.
Pitfall 4: Using a Plain List or Set Instead of a Sorted Structure
A natural but inefficient instinct is to store online stations in a plain Python set and compute the minimum with min(...) on each type-1 query:
ans.append(min(online_by_root[root])) # O(m) per query — too slow
This turns each query into O(m), leading to O(q · c) overall, which times out on large inputs.
Solution: Use a SortedList (or TreeSet/std::set) so the minimum is online_by_root[root][0] in O(1) access (O(log m) for membership checks and deletions). This preserves the intended O((c + n + q) · log c) complexity.
Pitfall 5: Wrong Membership Test vs. Empty-Set Check Order
If you check "is the grid empty" before checking "is station x itself online," you can return the smallest online station even when x is online — which is correct only by coincidence (since x would also be in the set). The real bug appears when you forget to handle the x-online case at all and always return the minimum:
# WRONG: ignores that an online x must answer itself if online_by_root[root]: ans.append(online_by_root[root][0]) else: ans.append(-1)
For a type-1 query on an online station x, the answer must be x itself, not the smallest online id in the grid.
Solution: Test station in online_by_root[root] first and return station; only fall back to the minimum (or -1) when x is offline:
if station in online_by_root[root]: ans.append(station) elif online_by_root[root]: ans.append(online_by_root[root][0]) else: ans.append(-1)
Ready to land your dream job?
Unlock your dream job with a 5-minute quiz for a personalized study roadmap!
Get My RoadmapWhich of these pictures shows the visit order of a depth-first search?

Recommended Readings
https assets algo monster cover_photos dfs svg Depth First Search Prereqs Recursion Review problems recursion_intro Trees problems tree_intro With a solid understanding of recursion under our belts we are now ready to tackle one of the most useful techniques in coding interviews Depth First Search DFS As the name suggests
https assets algo monster cover_photos bfs svg Breadth First Search on Trees Hopefully by this time you've drunk enough DFS Kool Aid to understand its immense power and seen enough visualization to create a call stack in your mind Now let me introduce the companion spell Breadth First Search BFS
Union Find Disjoint Set Union Data Structure Introduction Prerequisite Depth First Search Review problems dfs_intro So far in our DFS discussions we have mostly dealt with graphs with all the nodes connected to each other and thus forming one connected component Let's now look at a more general case where
Want a Structured Path to Master System Design Too? Don’t Miss This!