LeetCode – Most Stones Removed with Same Row or Column (Java)

The easiest solution for this problem is the union-find. The number of island problem can help understand how union-find works.

The basic idea is that we use a disjoint set to track each component. Whenever two stones can be connected, the number of islands decrease one. The final result, the number of movement, is the total number of stones – the number of islands.

Example 1:

Input: stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]
Output: 5

Note:

    1 <= stones.length <= 1000
    0 <= stones[i][j] < 10000

Java Solution 1 - Regular Disjoint Set

class Solution {
    int[] root = new int[1000]; //value is index
    int result = 0;
 
    public int removeStones(int[][] stones) {
        result = stones.length;
        for(int i=0; i<stones.length; i++){
            root[i]=i;    
        }
 
        for(int i=0; i<stones.length; i++){
            for(int j=i+1; j<stones.length; j++){
                if(stones[i][0]==stones[j][0] || stones[i][1]==stones[j][1]){
                    union(i, j);
                }
            }
        }
 
        return stones.length-result;
    }
 
    public void union(int i, int j){
        int ri = getRoot(i);
        int rj = getRoot(j);
 
        if(ri==rj){
            return;
        }
 
        root[getRoot(i)]=getRoot(j);
        result--;
    }
 
    public int getRoot(int i){
        while(i!=root[i]){
            i=root[i];
        }
 
        return i;
    }
}

Time complexity is O(N^2 * log(N)).

Java Solution 2 - Optimized Disjoint Set

class Solution {
    public int removeStones(int[][] stones) {
        DisjointSet ds = new DisjointSet(20000);
        for(int[] stone: stones){
            ds.union(stone[0], stone[1]+10000);
        }
 
        HashSet<Integer> set = new HashSet<>();
        for(int[] stone: stones){
            set.add(ds.find(stone[0]));
        }
 
        return stones.length - set.size();
    }
}
 
class DisjointSet{
    int[] parent;
    public DisjointSet(int size){
        parent = new int[size];
        for(int i=0; i<size; i++){
            parent[i] = i;
        }
    }
 
    public void union(int i, int j){
        parent[find(i)] = find(j);
    }
 
    public int find(int i){
        while(parent[i] != i){
            i = parent[i];
        }
 
        return i;
    }
}

Time complexity is log(20000)*N = O(N)

Leave a Comment