Most Stones Removed with Same Row or Column

medium graph union find dfs hash map

Problem

Stones sit on a 2D plane; you may remove a stone iff another stone shares its row or column. Return the maximum stones removable.

Inputstones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]
Output5
Connected components by shared row/col give answer = stones − components.

def removeStones(stones):
    parent = {}
    def find(x):
        parent.setdefault(x, x)
        if parent[x] != x: parent[x] = find(parent[x])
        return parent[x]
    def union(a, b):
        parent[find(a)] = find(b)
    for r, c in stones:
        union(("r", r), ("c", c))
    roots = {find(("r", r)) for r, c in stones}
    return len(stones) - len(roots)
function removeStones(stones) {
  const parent = new Map();
  function find(x) {
    if (!parent.has(x)) parent.set(x, x);
    if (parent.get(x) !== x) parent.set(x, find(parent.get(x)));
    return parent.get(x);
  }
  function union(a, b) { parent.set(find(a), find(b)); }
  for (const [r, c] of stones) union("r" + r, "c" + c);
  const roots = new Set();
  for (const [r] of stones) roots.add(find("r" + r));
  return stones.length - roots.size;
}
class Solution {
    Map<Integer, Integer> parent = new HashMap<>();
    public int removeStones(int[][] stones) {
        for (int[] s : stones) union(s[0], s[1] + 10000);
        Set<Integer> roots = new HashSet<>();
        for (int[] s : stones) roots.add(find(s[0]));
        return stones.length - roots.size();
    }
    int find(int x) { if (!parent.containsKey(x)) parent.put(x, x); if (parent.get(x) != x) parent.put(x, find(parent.get(x))); return parent.get(x); }
    void union(int a, int b) { parent.put(find(a), find(b)); }
}
unordered_map<int, int> parent;
int find(int x) { if (!parent.count(x)) parent[x] = x; if (parent[x] != x) parent[x] = find(parent[x]); return parent[x]; }
void unite(int a, int b) { parent[find(a)] = find(b); }
int removeStones(vector<vector<int>>& stones) {
    parent.clear();
    for (auto& s : stones) unite(s[0], s[1] + 10000);
    unordered_set<int> roots;
    for (auto& s : stones) roots.insert(find(s[0]));
    return (int)stones.size() - (int)roots.size();
}
Time: O(n α(n)) Space: O(n)