lintcode:被围绕的区域

本文介绍了如何使用深度优先搜索(DFS)和广度优先搜索(BFS)来解决二维矩阵中被'X'围绕的'O'区域问题。详细解释了两种算法的实现步骤,并通过代码示例展示了如何将边界联通的'O'替换为特殊字符,然后遍历矩阵将剩余的'O'替换为'X','*'恢复为'O'。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

被围绕的区域

给一个二维的矩阵,包含 'X' 和 'O', 找到所有被 'X' 围绕的区域,并用 'X' 填充满。

样例

给出二维矩阵:

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

把被 'X' 围绕的区域填充之后变为:

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

解题
参考岛屿的个数 然而我还是写不出来
programcreek 有下面的一段话:

This problem is similar to Number of Islands. In this problem, only the cells on the
boarders can not be surrounded. So we can first merge those O’s on the boarders like
in Number of Islands and replace O’s with ’#’, and then scan the board and replace all
O’s left (if any)

先将边界中联通的O换成*,这里利用深度优先

最后遍历数组,O->X  *->O,每个位置值遍历一次,不会出现混乱 

public class Solution {
    /**
     * @param board a 2D board containing 'X' and 'O'
     * @return void
     */
    public void surroundedRegions(char[][] board) {
        // Write your code here
        if(board == null || board.length == 0|| board[0].length == 0)
            return ;
        int row = board.length;
        int col = board[0].length;
        for(int i =0;i< row;i++){
            if(board[i][0] == 'O')
                merge(board,i,0);
            if(board[i][col-1] == 'O')
                merge(board,i,col-1);
        }
        for(int j =0;j< col;j++){
            if(board[0][j] == 'O')
                merge(board,0,j);
            if(board[row-1][j] == 'O')
                merge(board,row-1,j);
        }
        // O->X  *->O
        for(int i=0;i<row;i++){
            for(int j=0; j<col; j++){
                if(board[i][j] == 'O'){
                    board[i][j] = 'X';
                }else if(board[i][j] == '*'){
                    board[i][j] = 'O';
                }
            }
        }
    }
    // 将边界联通的O 换成 * 
    public void merge(char[][] board,int row,int col){
        if(row<0 || col<0 || row>= board.length || col>= board[0].length)
            return;
        if(board[row][col] != 'O')
            return;
        board[row][col] = '*';
        merge(board,row,col+1);
        merge(board,row+1,col);
        merge(board,row-1,col);
        merge(board,row,col-1);
    }
}
This solution causes java.lang.StackOverflowError, because for a large board, too many method calls are pushed to the stack and causes the overflow.

programcreek 中又给了一个广度优先的算法

比较复杂,先把程序复杂过来

public class Solution {
    // use a queue to do BFS
    private Queue<Integer> queue = new LinkedList<Integer>();
 
    public void solve(char[][] board) {
        if (board == null || board.length == 0)
            return;
 
        int m = board.length;
        int n = board[0].length;
 
        // merge O's on left & right boarder
        for (int i = 0; i < m; i++) {
            if (board[i][0] == 'O') {
                bfs(board, i, 0);
            }
 
            if (board[i][n - 1] == 'O') {
                bfs(board, i, n - 1);
            }
        }
 
        // merge O's on top & bottom boarder
        for (int j = 0; j < n; j++) {
            if (board[0][j] == 'O') {
                bfs(board, 0, j);
            }
 
            if (board[m - 1][j] == 'O') {
                bfs(board, m - 1, j);
            }
        }
 
        // process the board
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == 'O') {
                    board[i][j] = 'X';
                } else if (board[i][j] == '#') {
                    board[i][j] = 'O';
                }
            }
        }
    }
 
    private void bfs(char[][] board, int i, int j) {
        int n = board[0].length;
 
        // fill current first and then its neighbors
        fillCell(board, i, j);
 
        while (!queue.isEmpty()) {
            int cur = queue.poll();
            int x = cur / n;
            int y = cur % n;
 
            fillCell(board, x - 1, y);
            fillCell(board, x + 1, y);
            fillCell(board, x, y - 1);
            fillCell(board, x, y + 1);
        }
    }
 
    private void fillCell(char[][] board, int i, int j) {
        int m = board.length;
        int n = board[0].length;
        if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != 'O')
            return;
 
        // add current cell is queue & then process its neighbors in bfs
        queue.offer(i * n + j);
        board[i][j] = '#';
    }
}

update

public class Solution {
    /**
     * @param board a 2D board containing 'X' and 'O'
     * @return void
     */
    public void surroundedRegions(char[][] board) {
        // Write your code here
        if(board == null || board.length == 0 || board[0].length ==0)
            return;
        int row = board.length;
        int col = board[0].length;
        // 边界的 O 变为 P 
        for(int i =0;i<row;i++){ 
            if(board[i][0] == 'O')
                dfs(board,i,0,row,col);
            if(board[i][col-1] == 'O')
                dfs(board,i,col-1,row,col);
        }
        for(int j=0;j<col;j++){
            if(board[0][j] == 'O')
                dfs(board,0,j,row,col);
            if(board[row-1][j] == 'O')
                dfs(board,row-1,j,row,col);
                
        }
        // 中间的 O-> X
        for(int i=0;i<row;i++){
            for(int j=0;j<col;j++){
                if(board[i][j] == 'O')
                    board[i][j] = 'X';
            }
        }
        // P 还原 O
        for(int i=0;i<row;i++){
            for(int j=0;j<col;j++){
                if(board[i][j] == 'P')
                    board[i][j] = 'O';
            }
        }
    }
    // 将 ij 周围的 O - > P
    
    public void dfs(char[][] board,int i,int j,int row,int col){
        if(i<0 ||i>=row ||j<0 ||j>=col)
            return ;
        if(board[i][j]=='O'){
            board[i][j] ='P';
            dfs(board,i+1,j,row,col);
            dfs(board,i,j+1,row,col);
            dfs(board,i-1,j,row,col);
            dfs(board,i,j-1,row,col);
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值