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;
}
}
网友评论