UnionFind count islands

2018-02-26  本文已影响0人  Star_C

Question quoted from lintcode

Given a n,m which means the row and column of the 2D matrix and an array of pair A( size k). Originally, the 2D matrix is all 0 which means there is only sea in the matrix. The list pair has k operator and each operator has two integer A[i].x, A[i].y means that you can change the grid matrix[A[i].x][A[i].y] from sea to island. Return how many island are there in the matrix after each operator.
Example
Given n = 3, m = 3, array of pair A = [(0,0),(0,1),(2,2),(2,1)].
return [1,1,2,2].

Idea: This is still a very typical UnionFind question. The trick is that you have to check and connect the neighbours by searching in the pairs. given that UnionFind uses a HashMap implementation, you can conduct the search efficiently by exposing some more methods at class UnionFind.

/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */

class Cell {
    public final int rowNum;
    public final int colNum;

    public Cell(int rowNumber, int columnNumber) {
        this.rowNum = rowNumber;
        this.colNum = columnNumber;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Cell cell = (Cell) o;

        if (rowNum != cell.rowNum) return false;
        return colNum == cell.colNum;
    }

    @Override
    public int hashCode() {
        int result = rowNum;
        result = 31 * result + colNum;
        return result;
    }

    public List<Cell> crossNeighbors() {
        LinkedList<Cell> neighbors = new LinkedList<>();
        neighbors.add(new Cell(rowNum -1, colNum));
        neighbors.add(new Cell(rowNum +1, colNum));
        neighbors.add(new Cell(rowNum, colNum+1));
        neighbors.add(new Cell(rowNum, colNum-1));
        return neighbors;
    }
}

class UnionFind<T> {
    private Map<T, T> rootMap = new HashMap<>();
    private int count = 0;
    private void ensureExist(T element) {
        if (!rootMap.containsKey(element)) {
            rootMap.put(element, element);
            count++;
        }
    }
    
    public T find(T x) {
        ensureExist(x);
        T root = rootMap.get(x);
        if (root.equals(x)) 
          return root;
        rootMap.put(x, find(root));
        return rootMap.get(x);
    }
    
    public boolean exists(T x) {
        return rootMap.containsKey(x);
    }
    
    public void add(T x) {
        ensureExist(x);
    }
    
    public void connect(T a, T b) {
        T rootA = find(a);
        T rootB = find(b);
        if (rootA.equals(rootB)) return;
        rootMap.put(rootA, rootB);
        count--;
    }
    
    public int groupCount() {
        return count;
    }
}

class Islands {
    private UnionFind<Cell> uf = new UnionFind();
    private int rowLen = 0;
    private int colLen = 0;
    public Islands(int n, int m) {
        rowLen = n;
        colLen = m;
    }
    public void add(Cell pos) {
        
        boolean inBound = pos.rowNum >= 0 && pos.rowNum < rowLen && pos.colNum >= 0 && pos.colNum < colLen;
        if (!inBound) return;
        
        uf.add(pos);
        for(Cell nei: pos.crossNeighbors()) {
            if (uf.exists(nei)) {
                uf.connect(pos, nei);
            }
        }
    }
    public int count() {
        return uf.groupCount();
    }
}

public class Solution {
    /*
     * @param n: An integer
     * @param m: An integer
     * @param operators: an array of point
     * @return: an integer array
     */
    public List<Integer> numIslands2(int n, int m, Point[] operators) {
        // write your code here
        List<Integer> result = new LinkedList<Integer>();
        
        if (operators == null) return result;
        
        if (operators.length == 0) return result;
        
        Islands islands = new Islands(n, m);
        for(Point p : operators) {
            Cell c = new Cell(p.x, p.y);
            islands.add(c);
            result.add(islands.count());
        }
        return result;
    }
    
}
上一篇 下一篇

猜你喜欢

热点阅读