Imagine you are a network engineer trying to connect all computers in a network with the minimum number of cable operations.
You are given n computers numbered from 0 to n-1 and a list of connections where each connection connects two computers. You need to determine the minimum number of operations to connect all computers so that every computer can reach every other computer. An operation consists of removing an existing cable and placing it between two disconnected computers. Return the minimum number of operations needed, or -1 if it is impossible to connect all computers.
Edge cases: n = 1, connections = [] → 0 (single computer is trivially connected)n = 2, connections = [] → -1 (no cables to connect two computers)n = 3, connections = [[0,1],[1,2],[0,2]] → 0 (already fully connected with extra cable)
</>
IDE
def makeConnected(n: int, connections: list[list[int]]) -> int:public int makeConnected(int n, int[][] connections)int makeConnected(int n, vector<vector<int>>& connections)function makeConnected(n, connections)
def makeConnected(n, connections):
# Write your solution here
pass
class Solution {
public int makeConnected(int n, int[][] connections) {
// Write your solution here
return 0;
}
}
#include <vector>
using namespace std;
int makeConnected(int n, vector<vector<int>>& connections) {
// Write your solution here
return 0;
}
function makeConnected(n, connections) {
// Write your solution here
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: -1 when cables are sufficientIncorrect initial check for cables < n-1 or wrong component count.✅ Add a check: if len(connections) < n - 1: return -1 before counting components.
Wrong: 0 when network is disconnectedNot counting connected components correctly or ignoring disconnected nodes.✅ Use union-find or DFS to count all connected components accurately.
Wrong: Positive number when network is fully connectedReturning number of cables minus n instead of components minus one.✅ Return components - 1, not cables - n.
Wrong: TLE on large inputsUsing DFS or BFS repeatedly instead of union-find for large n.✅ Implement union-find with path compression and union by rank for O(α(n)) operations.
✓
Test Cases
Focus on handling minimal inputs and boundary conditions carefully.
Consider tricky cases where cables are just enough or insufficient.
Optimize your solution to handle large inputs efficiently using union-find.
t1_01basic
Input{"n":4,"connections":[[0,1],[0,2],[1,2]]}
Expected1
⏱ Performance - must finish in 2000ms
There are 3 computers connected with 3 cables. One cable can be moved to connect the 4th computer.
💡 Think about how many connected components the network has.
💡 Check if the number of cables is enough to connect all computers (at least n-1).
💡 The answer is the number of components minus one if cables are sufficient.
Why it failed: Returned wrong number of operations; likely missed counting connected components or miscalculated spare cables. Fix by ensuring to count components correctly and check if cables >= n-1.
✓ Correctly computed minimum operations using connected components and cable count.
There are 6 computers and 5 cables. The network has 2 connected components, so 2 operations are needed to connect all.
💡 Count how many connected components exist in the network.
💡 Verify if the number of cables is at least n-1 to allow full connection.
💡 Return components - 1 if cables are sufficient; otherwise -1.
Why it failed: Incorrect output due to not counting components or checking cable sufficiency properly. Fix by implementing union-find or DFS to count components and compare cables with n-1.
✓ Correctly identified components and cable sufficiency to compute operations.
t2_01edge
Input{"n":1,"connections":[]}
Expected0
⏱ Performance - must finish in 2000ms
Single computer with no cables is trivially connected; no operations needed.
💡 Consider the minimum number of cables needed for n=1.
💡 Check if the network is already connected when n=1.
💡 Return 0 since no operations are needed for a single node.
Why it failed: Returned non-zero for single node; fix by returning 0 immediately when n=1.
✓ Correctly handled single node case with zero operations.
t2_02edge
Input{"n":2,"connections":[]}
Expected-1
⏱ Performance - must finish in 2000ms
Two computers with no cables cannot be connected; return -1.
💡 Check if the number of cables is less than n-1.
💡 If cables are insufficient, return -1 immediately.
💡 No operations can connect the network without enough cables.
Why it failed: Returned non -1 despite insufficient cables; fix by checking cables < n-1 and returning -1.
✓ Correctly returned -1 when cables are insufficient.
t2_03edge
Input{"n":3,"connections":[[0,1],[1,2],[0,2]]}
Expected0
⏱ Performance - must finish in 2000ms
Three computers fully connected with an extra cable; no operations needed.
💡 Count connected components; should be 1 here.
💡 Check if cables are more than n-1, indicating spare cables.
💡 Return 0 since network is already fully connected.
Why it failed: Returned positive number despite fully connected network; fix by counting components correctly and returning components - 1.
✓ Correctly identified fully connected network with zero operations.
t3_01corner
Input{"n":5,"connections":[[0,1],[2,3]]}
Expected-1
⏱ Performance - must finish in 2000ms
Not enough cables to connect all 5 computers; return -1.
💡 Check if total cables are less than n-1.
💡 Count connected components to confirm network fragmentation.
💡 Return -1 if cables are insufficient regardless of components.
Why it failed: Returned non -1 despite insufficient cables; fix by adding initial check cables < n-1 return -1.
✓ Correctly returned -1 for insufficient cables.
t3_02corner
Input{"n":4,"connections":[[0,1],[2,3]]}
Expected-1
⏱ Performance - must finish in 2000ms
Two disconnected pairs with only 2 cables; not enough to connect all 4 computers.
💡 Count connected components; here 2 components exist.
💡 Check if cables are at least n-1 (3 for n=4).
💡 Return -1 if cables are insufficient.
Why it failed: Incorrectly returned 1 or 0; fix by verifying cables >= n-1 before computing operations.
✓ Correctly returned -1 due to insufficient cables.
Network is a chain fully connected with exactly n-1 cables; no operations needed.
💡 Count connected components; should be 1.
💡 Check if cables equal n-1, meaning no spare cables.
💡 Return 0 since network is connected without spare cables.
Why it failed: Returned positive number despite fully connected network; fix by returning components - 1 correctly.
✓ Correctly returned 0 for fully connected network with no spare cables.
t4_01performance
Input{"_description":"n=100000 at constraint boundary - executor generates this input"}
Expectednull
⏱ Performance - must finish in 2000ms
Test with n=100000 and up to 100000 connections to verify O(n + connections.length) or O(α(n)*connections.length) complexity within 2 seconds.
💡 Use union-find data structure for near O(1) union/find operations.
💡 Avoid DFS on large graphs; union-find is more efficient here.
💡 Implement path compression and union by rank/size to optimize.
Why it failed: Solution times out due to O(n^2) or DFS on large input; fix by using union-find with path compression and union by rank.
✓ Solution runs efficiently with union-find and passes performance test.
Practice
(1/5)
1. Examine the following buggy DFS code for counting provinces. Which line contains the subtle bug that can cause incorrect results or infinite recursion?
medium
A. Line 4: visited[city] = True
B. Line 2: for neighbor in graph[city]:
C. Line 1: def dfs(city: int):
D. Line 3: if not visited[neighbor]:
Solution
Step 1: Understand DFS visit marking
Visited nodes must be marked before recursive calls to avoid revisiting and infinite loops.
Step 2: Identify bug in visit marking
Marking visited after recursion causes repeated visits and possible infinite recursion.
Final Answer:
Option A -> Option A
Quick Check:
Visited marking must be before recursion to prevent cycles [OK]
Hint: Visited marking after recursion causes infinite loops [OK]
Common Mistakes:
Marking visited too late
Confusing visited marking with neighbor iteration
2. What is the time complexity of the optimal Union-Find algorithm with path compression and union by rank when finding the redundant connection in a graph with n edges?
medium
A. O(n²) because each union operation may traverse all nodes
B. O(n * α(n)) where α(n) is the inverse Ackermann function, nearly constant
C. O(n log n) due to sorting edges before union operations
D. O(n) because each edge is processed once without overhead
Solution
Step 1: Identify number of union/find operations
There are n edges, each triggers at most one union and two finds.
Step 2: Analyze complexity of find with path compression and union by rank
Each find/union operation runs in amortized O(α(n)) time, where α(n) is inverse Ackermann function, which grows extremely slowly.
Final Answer:
Option B -> Option B
Quick Check:
Union-Find with optimizations runs in near-linear time O(n * α(n)) [OK]
Hint: Inverse Ackermann function α(n) is almost constant [OK]
Common Mistakes:
Assuming O(n²) due to nested loops
Confusing sorting complexity with union-find
Ignoring path compression benefits
3. What is the time complexity of the optimal union-find approach with early contradiction detection for satisfiability of equality equations, assuming n equations and a fixed alphabet of 26 variables?
medium
A. O(n^2) due to repeated find operations without optimization
B. O(n α(n)) where α(n) is the inverse Ackermann function, nearly constant
C. O(n log n) because of union by rank and path compression overhead
D. O(n) since each equation is processed once with constant-time unions
Solution
Step 1: Identify union-find operations
Each union or find operation runs in amortized O(α(n)) time due to path compression and union by rank.
Step 2: Count total operations
Processing n equations involves at most 2n union/find calls, so total time is O(n α(n)).
Final Answer:
Option B -> Option B
Quick Check:
Union-find nearly linear time complexity [OK]
Hint: Inverse Ackermann function is nearly constant [OK]
Common Mistakes:
Confusing α(n) with log n
Assuming O(n) without considering find complexity
4. Suppose you want to find a minimum spanning forest (MST for each connected component) in a graph that may be disconnected. Which modification to the Kruskal's algorithm with union-find is necessary to correctly handle this scenario?
hard
A. Remove the break condition and process all edges to connect all components separately
B. Use DFS to find connected components first, then run Kruskal on each separately
C. Stop after adding n-1 edges, as usual, since MST covers all nodes
D. Add edges only if they connect nodes in the same component to avoid cycles
Solution
Step 1: Understand MST vs MST forest
In disconnected graphs, MST is a forest; stopping after n-1 edges assumes connectivity, which may not hold.
Step 2: Modify Kruskal to process all edges
Removing the break condition allows union-find to connect all components separately, building MST forest.
Final Answer:
Option A -> Option A
Quick Check:
Process all edges to cover disconnected components [OK]
Hint: Don't stop early if graph is disconnected; build MST forest instead [OK]
Common Mistakes:
Stopping early assuming graph is connected
Running DFS first adds unnecessary complexity
Misusing union-find to connect nodes in same component
5. Suppose the problem is modified so that edges can be added multiple times (i.e., duplicate edges allowed), and you need to find the first edge that creates a cycle considering duplicates. Which modification to the union-find approach correctly handles this scenario?
hard
A. Before union, check if the edge already exists in a hash set; if yes, return it immediately as redundant
B. Use union-find as usual but also maintain a visited edges set to detect duplicates causing cycles
C. Modify union-find to count the number of times an edge is added and only detect cycle when count > 1
D. Ignore duplicates and run union-find as usual; duplicates won't affect cycle detection
Solution
Step 1: Understand duplicate edges impact
Duplicate edges connect the same nodes multiple times, creating immediate cycles on second insertion.
Step 2: Modify algorithm to detect duplicates
Using a hash set to track edges allows detecting duplicates before union, returning the duplicate edge as redundant immediately.
Step 3: Why other options fail
Ignoring duplicates misses immediate cycle; counting edge additions in union-find is not standard; maintaining visited edges separately duplicates hash set logic.
Final Answer:
Option A -> Option A
Quick Check:
Hash set lookup detects duplicates in O(1) before union [OK]
Hint: Detect duplicates with a hash set before union [OK]
Common Mistakes:
Assuming union-find alone detects duplicates
Trying to count edges in union-find
Ignoring duplicate edges impact
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.