305 Number of Islands II

給一個m*n的matrix,初始值都是0,0表示是海,1表示是土地。給int[][] position,表示要加入土地的位置,addLand() 會根據給的position一一加入土地。問每一步addLand之後,matrix上會有多少個島。

Example

Input: m = 3, n = 3, positions = [[0,0], [0,1], [1,2], [2,1]]
Output: [1,1,2,3]

第一次 addLand(0,0)

1 0 0
0 0 0   Number of islands = 1
0 0 0

第二次 addLand(0,1)

1 1 0
0 0 0   Number of islands = 1
0 0 0

第三次addLand(1,2)

1 1 0
0 0 1   Number of islands = 2
0 0 0

第四次addLane(2,1)

1 1 0
0 0 1   Number of islands = 3
0 1 0

Idea 這是一題標準的Union Find題目。每一個島即是a set of 1s。 每當新加入一個position屬於某set,或導致某set和另個set變成同個set,就要Union 當需要知道某兩個位置是否屬於同個set,就要進行Find,來看兩者的parent是否相同。

Pseudocode

Create an ArrayList for saving # of island after each addLand operation
Create an int count to record current # of island
Each position on matrix have an id: n * x + y
Create a UnionFindSet

Each time add a position
    Set it's parent to itself
    count++
    check all four neighbors
        if neighbors is in the boundary
            Find(neighbor)
            if neighbor's parent is not -1
                Union 2 islands by rank
                count--
    result.add(count)

return result

Code

class Solution {
    public List<Integer> numIslands2(int m, int n, int[][] positions) {
        UnionFindSet set = new UnionFindSet(m*n);
        int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1}};
        List<Integer> result = new ArrayList<>();
        int count = 0;

        for(int[] p : positions){
            int idx = p[0]*n + p[1];
            count++;
            set.setParent(idx);//nx+y
            //check if four neighbors has 1
            for(int[] d : dirs){
                int nx = d[0] + p[0];
                int ny = d[1] + p[1];
                if(nx < 0 || nx >= m || ny < 0 || ny >= n) continue;
                int ni = n * nx + ny;//neighbor index
                if(set.Find(ni) != -1){
                    if(set.Union(idx, ni)){
                        count--;
                    }
                }
            }
            result.add(count);
        }

        return result;
    }
}

class UnionFindSet {
    private int[] parents;
    private int[] ranks;

    public UnionFindSet(int n) {
        parents = new int[n+1];
        ranks = new int[n+1];
        for(int i=0; i< parents.length; i++){
            parents[i] = -1;
            ranks[i] = 0;
        }
    }

    public void setParent(int u){
        parents[u] = u;
    }

    public boolean Union(int u, int v) {
        int pu = Find(u);
        int pv = Find(v);
        if(pu == pv)    return false;//no need to union, already in the same cluster
        if(ranks[pv] > ranks[pu])
            parents[pu] = pv;
        else if(ranks[pu] < ranks[pv])
            parents[pv] = pu;
        else{
            parents[pv] = pu;
            ranks[pu] += 1;
        }

        return true;
    }

    public int Find(int u){
        if(parents[u] == -1)    return -1;
        while(parents[u] != u){
            parents[u] = parents[parents[u]];
            u = parents[u];
        }
        return u;
    }
}

results matching ""

    No results matching ""