Problem Statement
Most Stones Removed
Picture a grid. We drop some stones on it, and each stone sits at a whole-number spot like (row, column). No two stones share the exact same spot. Here is the rule for taking a stone off the board: you can remove a stone if there is still another stone left somewhere in its same row or its same column. So a lonely stone with no neighbor in its row or column can never be removed. The question asks for the most stones we can possibly take away. The trick to seeing the answer is this: any group of stones that you can hop between by shared rows and columns is one connected blob. From a blob of k stones, you can keep removing until just one stone is left, so you remove k-1 of them. Add that up across all blobs and you get total stones minus the number of blobs.
Signals to notice
Brute force first
Try all removal orders — factorial. The order matters for what's removable at each step. That instinct is useful because it follows the prompt literally, but it usually keeps revisiting work the problem is begging you to organize.
The key insight
Union-Find: stones sharing a row or column are connected. Each connected group of k stones allows k-1 removals (leave one). Answer = totalStones - numberOfGroups. Once you hold onto the right piece of information from moment to moment, the problem feels less like trial and error and more like following a shape that was there all along.
Trace it on stones=[[0,0],[0,2],[1,1],[2,0],[2,2]] (indices 0..4)
i=0 (0,0): rowMap{0:0}, colMap{0:0}; parent=[0,1,2,3,4]
i=1 (0,2): row0 seen -> union(1,0); colMap{0:0,2:1}; parent=[0,0,2,3,4]
i=2 (1,1): row1 & col1 new -> rowMap{...,1:2}, colMap{...,1:2}; parent=[0,0,2,3,4]
i=3 (2,0): rowMap{...,2:3}; col0 seen -> union(3,0); parent=[0,0,2,0,4]
i=4 (2,2): row2 seen -> union(4,3)->parent[4]=0; col2 seen -> union(4,1) same root, skip; parent=[0,0,2,0,0]
roots = {find(0..4)} = {0,2} -> components=2
answer = n - components = 5 - 2 = 3What must stay true
Within a connected group (stones linked by shared rows/columns), you can always remove all but one stone. The maximum removals = total stones - number of connected groups. When you keep that truth intact, each local choice supports the larger solution instead of fighting it.
Shape of the loop
parent = [0..n-1]; rowMap = {}; colMap = {}
for i, (r, c) in stones:
if r in rowMap: union(i, rowMap[r]) else rowMap[r] = i
if c in colMap: union(i, colMap[c]) else colMap[c] = i
components = count of distinct find(i) for all i
return n - componentsPseudocode only — the full worked solution lives in the Solution tab.
Easy way to go wrong
Trying to simulate the removal process — you don't need to find the ORDER of removals, just the COUNT. Counting groups with Union-Find gives the answer directly. The fix is usually to return to the meaning of each move, not just the steps themselves.