Surrounded Regions

思考:只要将被包围的O和未被包围的O分开就好

方法

  • 1、用并查集(Union-find set)来区分,然后对原数组更改即可
  • 2、用BFS将与边缘O相邻的O(为被包围的O)全部变为#(或者其他符号),然后对原数组做相应更改

代码块

并查集

public class Solution {
    int[] unitArray;    //集合编号(隶属于哪一类)
    boolean[] edge; //是否被包围,每一类的edge都应该相同

    public void solve(char[][] board) {
        if(board.length < 3 || board[0].length < 3)
            return;
        unitArray = new int[board.length * board[0].length];
        edge = new boolean[unitArray.length];

        //initial the array
        for (int i = 0; i < unitArray.length; i++)
            unitArray[i] = i;
        for (int i = 0; i < unitArray.length; i++) {
            int r = i / board[0].length;
            int c = i % board[0].length;
            edge[i] = (board[r][c] == 'O' &&
                    (r == 0 || r == board.length - 1 
                     || c == 0 || c == board[0].length - 1));  // true表示没有被包围  
        }

        // span the matrix
        for (int i = 0; i < unitArray.length; i++) {
            int r = i / board[0].length;
            int c = i % board[0].length;
            int up = r - 1;
            int pre = c - 1;
            //the unper field
            if (up >= 0 && board[r][c] == board[up][c])
                unit(i, i - board[0].length);    //应该属于一类,unit一下
            //the pre field
            if (pre >=0 && board[r][c] == board[r][pre])
                unit(i, i - 1);
        }

        for (int i = 0; i < unitArray.length; i++) {
            int r = i / board[0].length;
            int c = i % board[0].length;
            if (board[r][c] =='O' && !edge[find(i)])
                board[r][c] = 'X';
        }

    }

    private void unit(int x, int y) {
        int rootX = find(x);   //找到这一类的根
        int rootY = find(y);   
        boolean edgeU = this.edge[rootX] || this.edge[rootY];  //只要有一个被包围,则都被包围
        unitArray[rootX] = rootY;
        this.edge[rootY] = edgeU;
    }

    private int find(int x) {
        if (unitArray[x] == x) return x;
        unitArray[x] = find(unitArray[x]);
        return unitArray[x];
    }
}

BFS方法

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

        if(board.length < 3 || board[0].length < 3)
            return;

        int n = board.length;
        int m = board[0].length;
        Queue<Integer> queue = new LinkedList<Integer>();

        //将四周的O,加入队列
        for(int i = 0; i < n; i++){
            if(board[i][0] == 'O')
                queue.add(i * m);
            if(board[i][m - 1] == 'O')
                queue.add(i * m + m - 1);
        }

        for(int j = 1; j < m - 1; j++){
            if(board[0][j] == 'O')
                queue.add(j);
            if(board[n - 1][j] == 'O')
                queue.add((n - 1) * m + j);
        }

        //BFS遍历,将没有被包围的O置为#
        BFS(queue, board);

        //留下来的O都是被包围的
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++){
                if(board[i][j] == '#')
                    board[i][j] = 'O';
                else if (board[i][j] == 'O')
                    board[i][j] = 'X';
            }
    }

    void BFS(Queue<Integer> queue, char[][] board){
        int m = board[0].length;
        int n = board.length;
        while(!queue.isEmpty()){
            int value = queue.poll();
            int row = value / m ;
            int col = value % m ;
            board[row][col] = '#';
            if(row - 1 >= 0 && board[row - 1][col] == 'O')
                queue.add((row - 1) * m  + col);
            if(row + 1 < n && board[row + 1][col] == 'O')
                queue.add((row + 1) * m + col);
            if(col - 1 >= 0 && board[row][col - 1] == 'O')
                queue.add(row * m + col - 1);
            if(col + 1 < m && board[row][col + 1] == 'O')
                queue.add(row* m + col + 1);
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值