Surrounded Regions (130)

 

1. BFS

时间 O(n*m)

空间 O(1)

1. 把所有的O标记为‘1’

2. 从四周向内看把标记为‘1’的变回'O' -> 时间O(n+m)

3. 把没有在2步骤中变化的‘1’变‘X’->时间O(n*m)

->时间O(n*m + n +m) 此方法比Union find要快

    private int row; 
    private int col;
    
    public void solve(char[][] board) {
        if(board == null || board.length == 0 || board[0].length == 0)
            return;
        row = board.length;
        col = board[0].length;
        for(int i = 0; i < row; i++)
            for(int j = 0; j < col; j++)
                if(board[i][j] == 'O')  board[i][j] = '1';
        
        for(int i = 0; i < row; i++){
            dfs(board, i, 0);
            dfs(board, i, col - 1);
        }
        for(int j = 0; j < col; j++){
            dfs(board, 0, j);
            dfs(board, row - 1, j);
        }
        for(int i = 0; i < row; i++)
            for(int j = 0; j < col; j++)
                if(board[i][j] == '1')
                    board[i][j] = 'X';
        return;
    }
    
    private void dfs(char[][] board, int x, int y){
        if(x < 0 || y < 0 || x >= row || y >= col || board[x][y] != '1')
            return;
        board[x][y] = 'O';
        int[] dx = {0,0,1,-1};
        int[] dy = {1,-1,0,0};
        for(int i = 0 ; i < 4; ++i){
            dfs(board, x + dx[i], y + dy[i]);
        }
    }

 

2. union find

时间O(N*M)

空间O(n*m)

 

首先定义Unionfindclass. 注意这里用rank来提高效率

class UnionFind {
    int[] father;
    int[] rank;
    public UnionFind(int n){
        father = new int[n];
        rank = new int[n]; 
        for(int i = 0 ; i < n; ++i){
            father[i] = i;
            rank[i] = 1;
        }
    }
    
    public void union(int a , int b){
        int father_a = find(a);
        int father_b = find(b);
        if(father_a!= father_b){
            if(rank[father_a] > rank[father_b]){
                father[father_b] = father_a;
                rank[father_a]++;
            }else{
                father[father_a] = father_b;
                rank[father_b]++;
            }
        }
    }
    
    public int find(int a){
        if(father[a] != a){
            father[a] = find(father[a]);
        }
        return father[a];
    }
}

然后主程序调用

对于每一个O, 如果在边上就合并入dummy node所在union。 

如果不在边上就合并入任意的O的集合。 这里再看四周四个是否为O并且合并。  

 

最后处理完以后再次遍历,如果当前node和dummy node在同一个集合,就不要改变字符

 -> 时间O(n*m *2)

 

    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;
        int dummyNode = n*m;
        UnionFind uf = new UnionFind(n*m +1);
        int[] dx = {0,0,1,-1};
        int[] dy = {1,-1,0,0};
        for(int i = 0; i < n; ++i){
            for(int j = 0 ; j < m; ++j){
                if(board[i][j] == 'X') continue;
                if(i== 0 || i == n-1 || j == 0 || j== m-1){  // this is on borader
                    uf.union(getNode(m,i,j), dummyNode);
                    continue;
                }
                for(int c = 0 ; c < 4; ++c){
                    if(board[i + dx[c]][j + dy[c]] == 'O')
                    uf.union(getNode(m,i,j), getNode(m,i + dx[c], j + dy[c]));   
                }
            }
        } 
        
        for(int i = 1; i < n-1; ++i){
            for(int j = 1 ; j < m-1; ++j){
                if(board[i][j] == 'O' && uf.find(getNode(m,i,j)) != uf.find(dummyNode)){
                    board[i][j] = 'X';
                }
            }
        }
    }
    private int getNode(int m, int i, int j){
        return i*m+j;
    }

 

posted on 2018-09-06 13:05  葫芦胡同749  阅读(96)  评论(0编辑  收藏  举报

导航