Number of Islands

两种解法; 解法1, dfs flooding来count有多少个unique islands. 这个会修改原数组.

解法二, union find, root最后的数量决定了多少个islands. 第一步认为所有'1'的点根为自身, 一共有n个岛屿, n为1的个数. 不断对4个方向做union, 做一次union操作, n的数量减一, 直到做完所有union. 一个需要注意的地方, union find的root array将二维数组map到了一维数组. a[x][y] = root[x*m+y];

    public int numIslands(char[][] grid) {

        if (grid==null || grid.length==0 || grid[0].length==0) return 0;
        int count = 0;
        for(int i=0;i<grid.length;i++)
            for(int j=0;j<grid[0].length;j++){
                if(grid[i][j]=='1'){
                    count++;
                    merge(grid, i, j);
                }
            }
            return count;
    }

    public void merge(char[][] grid, int i, int j){
        if(i< 0 || j < 0 || i>=grid.length || j>=grid[0].length || grid[i][j]!='1')
            return;
        grid[i][j] = '0';
        merge(grid, i-1,j);
        merge(grid, i+1, j);
        merge(grid, i, j-1);
        merge(grid, i, j+1);
    }

解法二: Union FInd

public int numIslands(char[][] grid){
        if(grid==null || grid.length==0 || grid[0].length==0) return 0;
        int[] x = {-1, 0, 0, 1};
        int[] y = {0,-1, 1, 0};
        UnionFind uf = new UnionFind(grid);
        for(int i=0;i<grid.length;i++)
            for(int j=0;j<grid[0].length;j++){
                if(grid[i][j]=='1'){
                    for(int k=0;k<4;k++){
                        int xx = i+x[k];
                        int yy = j+y[k];
                        if(xx>=0 && xx<grid.length && yy>=0 && yy<grid[0].length && grid[xx][yy]=='1')
                            uf.union(i*grid[0].length + j, xx*grid[0].length+yy);
                    } 
                }
            }
        return uf.count;
    }

}

 class UnionFind{
    int[] root;
    int row; int col;
    int count = 0;
    public UnionFind(char[][] grid){
        this.row = grid.length; this.col = grid[0].length;
        root = new int[row*col];
        Arrays.fill(root, -1);
        for(int i=0;i<row;i++)
            for(int j=0;j<col;j++){
                if(grid[i][j]=='1'){
                    root[i*col +j] = i*col+j;
                    count++;
                }
            }
    }

    public void union(int p1, int p2){
        int root1 = find(p1);
        int root2 = find(p2);
        if(root1!=root2){
         root[root2] = root1;
         count--;   
        }
    }

    public int find(int x){

        while(root[x]!=x) x= root[x];
        return x;

    }

}

Surrounded Regions

开始用了dfs flooding, 用list保存所有O的点, dfs如果返回true, 证明被完全包裹后, 将list里的点全部置为X. Stackover flow

public class Solution {
    public void solve(char[][] board) {
        if(board ==null || board.length==0||board[0].length==0) return;
        int m = board.length; int n = board[0].length;
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++){
                if(board[i][j]=='O'){
                    List<Integer> list = new ArrayList<Integer>();
                    if(dfs(board, list, i, j)){
                        for(int p : list){
                            board[p/n][p%n] = 'X';
                        }
                    }
                }
            }
    }

    public boolean dfs(char[][] board, List<Integer> list,  int i, int j){
        int m = board.length; int n = board[0].length;
        if(i<0||i>=m||j<0 ||j>=n) return false;
        if(board[i][j]=='X' || list.contains(i*n+j)) return true;
        list.add(i*n+j);
        if(dfs(board, list, i-1,j)==false) return false;
        if(dfs(board, list, i+1,j)==false) return false;
        if(dfs(board, list, i,j-1)==false) return false;
        if(dfs(board, list, i,j+1)==false) return false;

        return true;
    }
}

更好的方式是从四条边的O向中心扫描. 将扫到的O标记为S. 最后将O变成X, S变成O. 然而当边上所有的点都是O的时候, 还是会TLE. 一维数组都是0时.

public class Solution {
    public void solve(char[][] board) {
        if(board ==null || board.length==0||board[0].length==0) return;
        int m = board.length; int n = board[0].length;
        for(int i=0;i<m;i++){
            if(board[i][0]=='O')
                dfs(board, i, 0);
            if(board[i][n-1]=='O')
                dfs(board, i, n-1);
        }

        for(int j=0;j<n;j++){
            if(board[0][j]=='O')
                dfs(board, 0, j);
            if(board[m-1][j]=='O')
                dfs(board, m-1, j);
        }

        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++){
                if(board[i][j]=='O'){
                    board[i][j] = 'X';
                }
                if(board[i][j]=='#'){
                    board[i][j] = 'O';
                }
            }
    }

    public void dfs(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]=='X'||board[i][j]=='#') return;
        board[i][j] = '#';
        dfs(board, i-1,j);
        dfs(board, i+1,j);
        dfs(board, i,j-1);
        dfs(board, i,j+1);
    }
}

这道题还可以用Union Find, 如果O点的root在边上, 就保持为O, 否则设为X.

results matching ""

    No results matching ""