跳转至

130. Surrounded Regions

Leetcode Union Find Depth-First Search Breath-First Search

Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'.

A region is captured by flipping all 'O's into 'X's in that surrounded region.

Example:

X X X X
X O O X
X X O X
X O X X

After running your function, the board should be:

X X X X
X X X X
X X X X
X O X X

Explanation:

Surrounded regions shouldn’t be on the border, which means that any 'O' on the border of the board are not flipped to 'X'. Any 'O' that is not on the border and it is not connected to an 'O' on the border will be flipped to 'X'. Two cells are connected if they are adjacent cells connected horizontally or vertically.

分析

这道题其实思路是非常简单的:把二维数组放在UnionFind集合中,当出现'O'时,将'O'附近的'O'连接起来,形成connected component. 那么怎么判断'O'是否被围起来了呢?这里采用在原来数组外增加一圈'O'的方法,只需判断该'O'是否和外圈的'O'连接,来判断'O'是否被围起来。

public class Q130SurroundedRegions {
    public static void solve(char[][] board) {
        // corner case
        if (board.length < 3) return;

        int n = board.length;
        int m = board[0].length;

        // corner case
        if (m < 3) return;

        // add virtual points surrounds board
        int nn = n + 2, mm = m + 2;
        char[][] B = new char[nn][mm];
        for (int i = 0; i < nn; i++) {
            for (int j = 0; j < mm; j++) {
                if (i == 0 || j == 0 || j == mm - 1 || i == nn - 1)
                    B[i][j] = 'O';
                else
                    B[i][j] = board[i-1][j-1];
            }
        }



        // add union find data structure, 0 as virtual point
        WeightedPathCompressionQuickFind  uf = new WeightedPathCompressionQuickFind(nn*mm);
        int index;

        for (int i = 0; i < nn; i++) {
            for (int j = 0; j < mm; j++) {
                index = i * mm + j;

                if (virtualBoard[i][j] == 'O') {
                    // find adject 'O'
                    if ((j > 0) && (B[i][j-1] == 'O')) { //left
                        uf.union(index, index - 1);
                    }
                    if ((j < m - 1) && (B[i][j + 1] == 'O')) { // right
                        uf.union(index, index + 1);
                    }
                    if ((i > 0) && (B[i-1][j] == 'O')) { // top
                        uf.union(index, index - mm);
                    }
                    if ((i < n - 1) && (B[i+1][j] == 'O')) { // bottom
                        uf.union(index, index  + mm);
                    }
                }
            }
        }

        // flip it  if  'O' is captured,
        for (int i = 1; i < n - 1; i++) {
            for (int j = 1; j < m - 1; j++) {
                index = (i + 1) * mm + (j + 1); // index on virtual board
                if ((board[i][j] == 'O') && (!uf.connected(0, index))) {
                    board[i][j] = 'X';
                }
            }
        }
    }
}