[LeetCode] 130. Surrounded Regions Java

题目: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.

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'组成的区域被‘X’包含,那么将改‘O’区域替换为‘X’。我最开始想到的是,用一个visited[row][col]保存该点是否访问过,然后遍历矩阵,对遇到的非边界、为访问过的‘O’点进行区域查找,将区域用一个List<Integer[]> 保存,若不存在在边界的‘O’,那么该区域满足条件(其实就是图的宽度查找),但是这里用了递归,所以运行代码栈溢出。。。反向思维:从边界的‘O’点开始查找,如果有何边界的‘O’点相连的则不用替换(这里用一个'#'先替换),遍历所有的边界‘O’,最后对遍历一次矩阵,将所有的'O'转化为‘X’,然后在遍历一次将‘#’转回为‘O’,这样可以直接替换,不需要保存可能的值。
内存溢出代码:
public class Solution {
    public void solve(char[][] board) {
        int row = board.length;     //行数
        if(row==0) return;
        int col=board[0].length;      //列数
        boolean[][] visited = new boolean[row][col];
        for(int i=0;i<row;i++){
            for(int j=0;j<col;j++){
                List<Integer[]> union = new ArrayList<>();
                if((i!=0&&j!=0&&i!=row-1&&j!=col-1)&&(board[i][j]=='O')&&(!visited[i][j])){     //遍历到非边界且未被访问过的'o'
                    union.clear();     // 遍历到一个未被访问的o点,就访问该点能到达的所有'o'点
                    boolean[] isNeedChange = {true};     //判断该'o'点能达到的区域是否满足要求
                    findUnion(visited,union,i,j,board,isNeedChange);
                    if(isNeedChange[0]){     //该区域需要改变,那就改变咯
                        for(int m=0;m<union.size();m++){
                            Integer[] temp = union.get(m);
                            board[temp[0]][temp[1]] = 'X';
                        }
                    }
                }
            }
        }
    }

    public void findUnion(boolean[][] visited,List<Integer[]> union,int i,int j,char[][] board,boolean[] isNeedChange){     //查找某一个'o'区域
        int row = board.length;
        int col = board[0].length;
        if(visited[i][j]) return;           //该点已经访问过,直接返回
        visited[i][j] =true;
        Integer[] indexs = {i,j};
        if(isNeedChange[0]==false) {
            union.clear();
            return;
        }
        else {
            union.add(indexs);
        }
        if(i-1>=0&&board[i-1][j]=='O'){     //
            if(i-1==0) isNeedChange[0]=false;   //边界点有为'o'的
            findUnion(visited,union,i-1,j,board,isNeedChange);
        }
        if(i+1<row&&board[i+1][j]=='O'){     //
            if(i+1==row-1) isNeedChange[0]=false;   //边界点有为'o'的
            findUnion(visited,union,i+1,j,board,isNeedChange);
        }
        if(j-1>=0&&board[i][j-1]=='O'){     //
            if(j-1==0) isNeedChange[0]=false;   //边界点有为'o'的
            findUnion(visited,union,i,j-1,board,isNeedChange);
        }
        if(j+1<col&&board[i][j+1]=='O'){    //
            if(j+1==col-1) isNeedChange[0]=false;   //边界点有为'o'的
            findUnion(visited,union,i,j+1,board,isNeedChange);
        }
    }
}

 AC代码:

public class Solution {
    public void solve(char[][] board) {
        int row = board.length;     //行数
        if(row==0) return;
        int col=board[0].length;      //列数
        Queue<Integer[]> queue = new LinkedList<>();       //记录需要被替换的点,初始时是边界的点
        for(int i=0;i<col;i++){
            if(board[0][i]=='O') {      //上边界点为'O',宽度查找
                Integer[] index={0,i};
                queue.offer(index);
            }
        }

        for(int i=0;i<col;i++){
            if(board[row-1][i]=='O') {  //下边界有'O'
                Integer[] index={row-1,i};
                queue.offer(index);
            }
        }

        for(int i=1;i<row-1;i++){     //左边界点有’‘
            if(board[i][0]=='O') {
                Integer[] index={i,0};
                queue.offer(index);
            }
        }
        for(int i=1;i<row-1;i++){
            if(board[i][col-1]=='O') {
                Integer[] index={i,col-1};
                queue.offer(index);
            }
        }
        while(!queue.isEmpty()){
            Integer[] index = queue.poll();
            int m = index[0],n=index[1];
            if(board[m][n]=='O'){     //初次遍历到该点
                board[m][n]='#';  //将该点置为'#'
                if(m>=1&&board[m-1][n]=='O'){
                    Integer[] temp = {m-1,n};
                    queue.offer(temp);
                }
                if(m<row-1&&board[m+1][n]=='O'){
                    Integer[] temp = {m+1,n};
                    queue.offer(temp);
                }
                if(n>=1&&board[m][n-1]=='O'){
                    Integer[] temp = {m,n-1};
                    queue.offer(temp);
                }
                if(n<col-1&&board[m][n+1]=='O'){
                    Integer[] temp = {m,n+1};
                    queue.offer(temp);
                }
            }
        }
        for(int i=0;i<row;i++){     //替换被包含的'O'点
            for (int j=0;j<col;j++){
                if(board[i][j]=='O')
                    board[i][j]='X';
            }
        }
        for(int i=0;i<row;i++){     //替换回来
            for (int j=0;j<col;j++){
                if(board[i][j]=='#')
                    board[i][j]='O';
            }
        }
        return;
    }
}