[Leetcode] Surrounded Regions 找出被包围的区域

632 查看

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.

For 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

原题链接

边缘搜索替换法

复杂度

时间 O(MN) 空间 O(MN)

思路

从矩阵的四条边上的点作为起点,搜索连续的一块区域上值为O的点并赋为一个临时变量。这里我们用BFS或DFS进行搜索。对四条边上所有点都进行过这个步骤后,矩阵内剩余的O就是被包围的O。此时再对所有点遍历一遍,将临时变量赋回O,而剩余的O则赋为X。

注意

用队列实现BFS时,赋临时变量B时要在将周边点加入队列时就赋值,减少while循环的次数,否则Leetcode会超时

代码

广度优先 BFS

public class Solution {
    public void solve(char[][] board) {
        for(int i = 0; i < board.length; i++){
            for(int j = 0; j < board[0].length; j++){
                if((i == 0 || j == 0 || i == board.length - 1 || j == board[0].length - 1) && (board[i][j]=='O')){
                    Queue<Integer> q = new LinkedList<Integer>();
                    q.offer(i * board[0].length + j);
                    board[i][j] = 'B';
                    while(!q.isEmpty()){
                        Integer key = q.poll();
                        int x = key / board[0].length;
                        int y = key % board[0].length;
                        if(x > 0 && board[x-1][y]=='O'){
                            q.offer((x-1) * board[0].length + y);
                            board[x-1][y] = 'B';
                        }
                        if(x < board.length - 1  && board[x+1][y]=='O'){
                            q.offer((x+1) * board[0].length + y);
                            board[x+1][y] = 'B';
                        }
                        if(y > 0  && board[x][y-1]=='O'){
                            q.offer(x * board[0].length + y - 1);
                            board[x][y-1] = 'B';
                        }
                        if(y < board[0].length - 1  && board[x][y+1]=='O'){
                            q.offer(x * board[0].length + y + 1);
                            board[x][y+1] = 'B';
                        }
                    }
                }
            }
        }
        for(int i = 0; i < board.length; i++){
            for(int j = 0; j < board[0].length; j++){
                if(board[i][j]=='O') board[i][j]='X';
                if(board[i][j]=='B') board[i][j]='O';
            }
        }
    }
}

深度优先 DFS

public class Solution {
    static class Pair {
        public int first;
        public int second;
        public Pair(int f, int s) {
            first = f;
            second = s;
        }
    }
    
    public void solve(char[][] board) {
        if(board == null || board.length == 0) {
            return ;
        }
        for(int i = 0; i < board[0].length; ++i) {
            if(board[0][i] == 'O') {
                markUnflippable(board,0,i);
            }
        }
        for(int i = 0; i < board[board.length-1].length; ++i) {
            if(board[board.length-1][i] == 'O') {
                markUnflippable(board,board.length-1,i);
            }
        }
        for(int i = 0 ; i < board.length; ++i) {
            if(board[i][0] == 'O') {
                markUnflippable(board,i,0);
            }
        }
        for(int i =0; i < board.length; ++i) {
            if(board[i][board[i].length-1] == 'O') {
                markUnflippable(board,i,board[i].length-1);
            }
        }
    
        // modify the board
        for(int i = 0; i < board.length; ++i) {
            for(int j = 0; j < board[i].length; ++j) {
                if(board[i][j] == 'O') {
                    board[i][j] = 'X';
                } else if(board[i][j] == 'U') {
                    board[i][j] = 'O';
                }
            }
        }
    }
    
    public void markUnflippable(char[][] board, int r, int c) {
        int[] dirX = {-1,0,1,0};
        int[] dirY = {0,1,0,-1};
        ArrayDeque<Pair> stack = new ArrayDeque<>();
        stack.push(new Pair(r,c));
        while(!stack.isEmpty()) {
            Pair p = stack.pop();
            board[p.first][p.second] = 'U';
            for(int i = 0; i < dirX.length; ++i) {
                if(p.first + dirX[i] >= 0 && p.first + dirX[i] < board.length && p.second + dirY[i] >= 0 && p.second +dirY[i] < board[p.first + dirX[i]].length && board[p.first+dirX[i]][p.second+dirY[i]] == 'O') {
                    stack.push(new Pair(p.first+dirX[i],p.second+dirY[i]));
                }
            }
        }
    }
}