305. Number of Islands II (union-find)

naive

BFS in leetcode 200, each cell call BFS one time

T: O(mn*mn)

S: O(mn)

union find

T: O(mn)

S: O(mn)

class Solution {
    private int[][] dirs = {{1,0},{0,1},{-1,0},{0,-1}};
    public List<Integer> numIslands2(int m, int n, int[][] positions) {
        List<Integer> res = new ArrayList<>();
        if (positions == null || positions.length == 0) {
            return res;
        }
        UnionFind uf = new UnionFind();
        boolean[][] isLand = new boolean[m][n];
        
        for (int[] position : positions) {
            int x = position[0];
            int y = position[1];
            if (isLand[x][y]) {
                res.add(uf.getNumOfSet());
                continue;
            }
            
            isLand[x][y] = true;
            uf.add(toId(x, y, n));
            
            for (int[] dir : dirs) {
                int neighborX = x + dir[0];
                int neighborY = y + dir[1];
                if (!isValid(neighborX, neighborY, m, n, isLand)) {
                    continue;
                }
                uf.union(toId(x, y, n), toId(neighborX, neighborY, n));
            }
            res.add(uf.getNumOfSet());
        }
        return res;
    }
    /*
      m = 4, n = 9 (4 row, 9 col)
      0  1  2  3 4 5 6 7 8  
      9 10 11 12 => (1,2) => 1*9 + 2 = 11, x*n + y 
    */
    private int toId(int x, int y, int n) {
        return x*n + y;
    }
    private boolean isValid(int x, int y, int m, int n, boolean[][] isLand) {
        return x >= 0 && x < m && y >= 0 && y < n && isLand[x][y];
    }
}

class UnionFind {
    private Map<Integer, Integer> parent;
    private Map<Integer, Integer> sizeOfSet;
    private int numOfSet = 0;
    UnionFind() {
        this.parent = new HashMap<>();
        this.sizeOfSet = new HashMap<>();
    }
    public void add(int x) {
        if (parent.containsKey(x)) {
            return;
        }
        parent.put(x, null);
        sizeOfSet.put(x, 1);
        numOfSet++;
    }
    public int find(int x) {
        int root = x;
        while (parent.get(root) != null) {
            root = parent.get(root);
        }
        
        while (x != root) {
            int xParent = parent.get(x);
            parent.put(x, root);
            x = xParent;
        }
        return root;
    }
    public void union(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX != rootY) {
            parent.put(rootX, rootY);
            numOfSet--;
            sizeOfSet.put(rootY, sizeOfSet.get(rootX)+sizeOfSet.get(rootY));
        }
    }
    public boolean isConnected(int x, int y) {
        return find(x) == find(y);
    }
    public int getNumOfSet() {
        return numOfSet;
    }
    public int getSizeOfSet(int x) {
        if (!sizeOfSet.containsKey(x)) {
            return 0;
        }
        return sizeOfSet.get(find(x));
    }
}

new version

final version - simpler union find

T: O(mn)

S: O(mn)

Last updated

Was this helpful?