L477 Surrounded Regions

Given a 2D board containing'X'and'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 capture all regions surrounded by'X', the board should be:

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

这题有多种解法,解法一:BFS

public void solve(char[][] board) {

    if (board == null || board.length == 0 || board[0].length == 0) {
        return;
    }

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

    // fill the edge 'O' with 'T'
    for (int i = 0; i < n; i++) {
        if (board[i][0] == 'O') {
            board = bfsfill(board, i, 0, 'O', 'T');
        }

        if (board[i][m - 1] == 'O') {
            board = bfsfill(board, i, m - 1, 'O', 'T');
        }
    }

    for (int j = 0; j < m; j++) {
        if (board[0][j] == 'O') {
            board = bfsfill(board, 0, j, 'O', 'T');
        }

        if (board[n - 1][j] == 'O') {
            board = bfsfill(board, n - 1, j, 'O', 'T');
        }
    }

    // turn rest of 'O' to 'X'
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (board[i][j] == 'O') {
                board = bfsfill(board, i, j, 'O', 'X');
            }
        }
    }

    // turn 'T' back to 'O'
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (board[i][j] == 'T') {
                board = bfsfill(board, i, j, 'T', 'O');
            }
        }
    }
}

int[] x = { 0, 0, 1, -1 };
int[] y = { 1, -1, 0, 0 };

private char[][] bfsfill(char[][] M, int i, int j, char src, char target) {
    Queue<Integer> q = new LinkedList<>();
    int m = M[0].length;
    q.offer(i * m + j);
        M[i][j] = target;

    while (!q.isEmpty()) {
        int cur = q.poll();
        int curi = cur / m;
        int curj = cur % m;

        for (int k = 0; k < 4; k++) {
            int nexti = curi + x[k];
            int nextj = curj + y[k];

            if (inBound(M, nexti, nextj) && M[nexti][nextj] == src) {
                M[nexti][nextj] = target;
                q.offer(nexti * m + nextj);
            }
        }
    }

    return M;
}

private boolean inBound(char[][] M, int row, int col) {
    if (row < 0 || col < 0 || row >= M.length || col >= M[0].length) {
        return false;
    }

    return true;
}

方法二:Union Find

public class Solution {
    /**
     * @param board a 2D board containing 'X' and 'O'
     * @return void
     */

    HashMap<Integer, DSNode> map = new HashMap<>(); 
    public void surroundedRegions(char[][] board) {
        if (board == null || board.length == 0 || board[0].length == 0) {
            return;
        }

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

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                makeSet(i * m + j);
            }
        }

        DSNode edgesNodes = null;
        for (int i = 0; i < n; i++) {
            if (board[i][0] == 'O') {
                if (edgesNodes == null) {
                    edgesNodes = unionNei(i, 0, board);
                } else {
                    connect(edgesNodes, unionNei(i, 0, board));
                }
            }

            if (board[i][m - 1] == 'O') {
                if (edgesNodes == null) {
                    edgesNodes = unionNei(i, m - 1, board);
                } else {
                    connect(edgesNodes, unionNei(i, m - 1, board));
                }
            }
        }

        for (int j = 0; j < m; j++) {
            if (board[0][j] == 'O') {
                if (edgesNodes == null) {
                    edgesNodes = unionNei(0, j, board);
                } else {
                    connect(edgesNodes, unionNei(0, j, board));
                }
            }

            if (board[n - 1][j] == 'O') {
                if (edgesNodes == null) {
                    edgesNodes = unionNei(n - 1, j, board);
                } else {
                    connect(edgesNodes, unionNei(n - 1, j, board));
                }
            }
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (board[i][j] == 'O' && (findSet(map.get(i * m + j)) != edgesNodes)) {
                    board[i][j] ='X';
                }
            }
        }

    }

    private DSNode unionNei(int row, int col, char[][] board) {
        int n = board.length;
        int m = board[0].length;

        boolean[][] visited = new boolean[n][m];
        Queue<Integer> q = new LinkedList<>();
        q.offer(row * m + col);
        visited[row][col] = true;

        DSNode res = map.get(row * m + col);

        int[] x = {0, 0, 1, -1};
        int[] y = {1, -1, 0, 0};

        while (!q.isEmpty()) {
            Integer cur = q.poll();
            int curi = cur / m;
            int curj = cur % m;

            for (int k = 0; k < 4; k++) {
                int nexti = curi + x[k];
                int nextj = curj + y[k];

                if (inBound(nexti, nextj, n, m) && board[nexti][nextj] == 'O' && !visited[nexti][nextj]) {
                    visited[nexti][nextj] = true;
                    connect(res, map.get(nexti * m + nextj));
                    q.offer(nexti * m + nextj);
                }
            }
        }

        return res;
    }

    private boolean inBound(int row, int col, int n, int m) {
        if (row < 0 || col < 0 || row >= n || col >= m) {
            return false;
        }

        return true;
    }

    private DSNode connect(DSNode node1, DSNode node2) {
        DSNode p1 = findSet(node1);
        DSNode p2 = findSet(node2);

        if (p1 == p2) {
            return p1;
        }

        if (p1.rank >= p2.rank) {
            p1.rank += p2.rank;
            p2.parent = p1;
            p2.rank = -1;
            return p1;
        } else {
            p2.rank += p1.rank;
            p1.parent = p2;
            p1.rank = -1;
            return p2;
        }
    }

    private DSNode findSet(DSNode node) {
        DSNode p = node.parent;

        if (p == node) {
            return node;
        }

        return p.parent = findSet(p.parent);
    }


    private void makeSet(int node) {
        DSNode newNode = new DSNode(node);
        newNode.rank = 1;
        newNode.parent = newNode;
        map.put(node, newNode);
    }
}

class DSNode {
    int val;
    int rank;
    DSNode parent;

    public DSNode(int v) {
        val = v;
    }
}

Last updated