Gyh's Braindump

200. Number of Islands

tags
BFS, DFS, Union Find
source
leetcode

* Edge Cases

Solution 1 - DFS

NOTE: if it’s acceptable to revise the original array, space complexity can be O(1)

class Solution {
  void dfs(char[][] grid, int r, int c, boolean[][] seen) {
    int nr = grid.length;
    int nc = grid[0].length;

    if (r < 0 || c < 0 || r >= nr || c >= nc || grid[r][c] == '0' || seen[r][c]) {
      return;
    }

    seen[r][c] = true;
    dfs(grid, r - 1, c, seen);
    dfs(grid, r + 1, c, seen);
    dfs(grid, r, c - 1, seen);
    dfs(grid, r, c + 1, seen);
  }

  public int numIslands(char[][] grid) {
    if (grid == null || grid.length == 0) {
      return 0;
    }

    int nr = grid.length;
    int nc = grid[0].length;
    boolean[][] seen = new boolean[nr][nc];
    int num_islands = 0;
    for (int r = 0; r < nr; ++r) {
      for (int c = 0; c < nc; ++c) {
        if (grid[r][c] == '1' && !seen[r][c]) {
          ++num_islands;
          dfs(grid, r, c, seen);
        }
      }
    }

    return num_islands;
  }
}

Complexity

  • time: O(MN)
  • space: O(MN)

Solution 2 - BFS

class Solution {
  public int numIslands(char[][] grid) {
    if (grid == null || grid.length == 0) {
      return 0;
    }

    int nr = grid.length;
    int nc = grid[0].length;
    int num_islands = 0;

    for (int r = 0; r < nr; ++r) {
      for (int c = 0; c < nc; ++c) {
        if (grid[r][c] == '1') {
          ++num_islands;
          grid[r][c] = '0'; // mark as visited
          Queue<Integer> neighbors = new LinkedList<>();
          neighbors.add(r * nc + c);
          while (!neighbors.isEmpty()) {
            int id = neighbors.remove();
            int row = id / nc;
            int col = id % nc;
            if (row - 1 >= 0 && grid[row-1][col] == '1') {
              neighbors.add((row-1) * nc + col);
              grid[row-1][col] = '0';
            }
            if (row + 1 < nr && grid[row+1][col] == '1') {
              neighbors.add((row+1) * nc + col);
              grid[row+1][col] = '0';
            }
            if (col - 1 >= 0 && grid[row][col-1] == '1') {
              neighbors.add(row * nc + col-1);
              grid[row][col-1] = '0';
            }
            if (col + 1 < nc && grid[row][col+1] == '1') {
              neighbors.add(row * nc + col+1);
              grid[row][col+1] = '0';
            }
          }
        }
      }
    }

    return num_islands;
  }
}

Complexity

  • time: O(MN)
  • space: O(MN)

Solution 3 - Union Find

NOTE: only two directions are needed

class Solution {

    int[] par;

    public int numIslands(char[][] a) {
        if(a.length==0) return 0;

        int n = a.length, m=a[0].length;
        par = new int[m*n];
        Arrays.fill(par, -1);

        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){

                if(a[i][j]=='1'){
                    par[i*m+j]=i*m+j; // note, that `par` was filled witn -1 values
                    if(i>0 && a[i-1][j]=='1') union(i*m+j, (i-1)*m+j); // union current+top
                    if(j>0 && a[i][j-1]=='1') union(i*m+j, i*m+(j-1)); // union current+left
                }

            }
        }

        Set<Integer> set = new HashSet<>();
        for(int k=0;k<par.length;k++){
            if(par[k]!=-1) set.add(find(k));
        }
        return set.size();
    }

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

    void union(int x, int y){
        int px = find(x);
        int py = find(y);
        par[px]=par[py];
    }

}

Complexity

  • time: O(MN) when Rank and Path Compression are implemented
  • space: O(MN)