Given N x M character matrix A of O's and X's, where O = white, X = black.
Return the number of black shapes. A black shape consists of one or more adjacent X's (diagonals not included)
Input Format:
The First and only argument is a N x M character matrix.
Output Format:
Return a single integer denoting number of black shapes.
Constraints:
1 <= N,M <= 1000
A[i][j] = 'X' or 'O'
Example:
Input 1:
A = [ OOOXOOO
OOXXOXO
OXOOOXO ]
Output 1:
3
Explanation:
3 shapes are :
(i) X
X X
(ii)
X
(iii)
X
X
Note: we are looking for connected shapes here.
XXX
XXX
XXX
is just one single connected black shape.
Solution:
BFS + union find
Time: O(E + V)
public class Solution { static class UF { private int count; private int[] parent; private int[] size;
public UF(int n) { count = 0; parent = new int[n]; size = new int[n]; for (int i = 0; i < n; i ++) { parent[i] = i; size[i] = 1; } }
public int find(int x) { while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; } return x; }
public void union(int x, int y) { int rootX = find(x); int rootY = find(y); if (rootX == rootY) { return; } if (size[rootX] <= size[rootY]) { parent[rootX] = rootY; size[rootY] += size[rootX]; } else { parent[rootY] = rootX; size[rootX] += size[rootY]; } count --; }
public int count() { return this.count; }
public void incrementCount() { this.count ++; } }
static class Node { int x; int y;
public Node(int x, int y) { this.x = x; this.y = y; }
public int index(int n) { return x * n + y; }
public boolean valid(int m, int n) { return x >= 0 && x < m && y >= 0 && y < n; }
@Override public int hashCode() { int hash = 17; hash += this.x * 31; hash += this.y * 31; return hash; }
@Override public boolean equals(Object o) { Node n = (Node) o; return n.x == x && n.y == y; } }
public int black(String[] A) { int m = A.length; int n = A[0].length(); Queue<Node> queue = new ArrayDeque<>(); Set<Node> visited = new HashSet<>(); UF blk = new UF(m * n); int[] dx = new int[]{-1,0,1,0}; int[] dy = new int[]{0,1,0,-1}; for (int i = 0; i < m; i ++) { String s = A[i]; for (int j = 0; j < n; j ++) { char c = s.charAt(j); if (c == 'X') { blk.incrementCount(); queue.offer(new Node(i, j)); } } } while (!queue.isEmpty()) { Node node = queue.poll(); if (visited.add(node)) { for (int i = 0; i < 4; i ++) { Node next = new Node(node.x + dx[i], node.y + dy[i]); if (next.valid(m, n) && A[next.x].charAt(next.y) == 'X') { blk.union(node.index(n), next.index(n)); queue.offer(next); } } } } return blk.count(); } }