200 - number of islands

subject

Give you a two-dimensional grid composed of '1' (land) and '0' (water). Please calculate the number of islands in the grid.

Islands are always surrounded by water, and each island can only be formed by adjacent land connections in the horizontal and / or vertical direction.

In addition, you can assume that all four sides of the mesh are surrounded by water.

Example 1:

Input: grid =[
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
Output: 1
Example 2:

Input: grid =[
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
Output: 3

Solution 1 dfs

var numIslands = function(grid) {
  function dfs(grid,i,j){//Format!
    // Recursive termination condition
    if(i<0||i>=grid.length||j<0||j>=grid[0].length||grid[i][j]==='0'){
       return  
    }
    grid[i][j]='0' // The passed is marked with 0 and two brackets 😂
    dfs(grid, i + 1, j)
    dfs(grid, i, j + 1)
    dfs(grid, i - 1, j)
    dfs(grid, i, j - 1)
  }
  let count=0
  for(let i=0;i<grid.length;i++){
      for(let j=0;j<grid[0].length;j++){
          if(grid[i][j]==='1'){
              dfs(grid,i,j)
              count++
          }
      }
  }
 return count
};

Notes:

  1. void traverse(TreeNode root) {
        // Judge base case
        if (root == null) {
            return;
        }
        // Access two adjacent nodes: left child node and right child node
        traverse(root.left);
        traverse(root.right);
    }
    //dfs framework
    
  2. How to avoid such repeated traversal? The answer is to mark the lattice that has been traversed. Taking the island problem as an example, we need to do DFS traversal on all land grids with a value of 1. Every time we walk through a land grid, we change the value of the grid to 2, so that when we encounter 2, we know that this is the traversed grid. That is, each grid may take three values:

    0 - Ocean grid
    1 - land grid (not traversed)
    2 - land grid (traversed)

  3. If you do not change the land on the same island with it to 0, DFS will count an island repeatedly when it traverses them

  4. How to find all 1 on the same island
    DFS, with current 1 as the entry
    What DFS does:
    Change the current 1 to 0
    The top, bottom, left and right of the current coordinate recurs in turn, and the 1 of the same island becomes 0
    dfs exit: out of matrix boundary, or 0 encountered. Don't sink the island, return directly

Solution 2 bfs

const numIslands = (grid) => {
  let count = 0
  let queue = []
  for (let i = 0; i < grid.length; i++) {
    for (let j = 0; j < grid[0].length; j++) {
      if (grid[i][j] === '1') {
        count++
        grid[i][j] = '0' // Mark to avoid repeated traversal
        queue.push([i, j])
        turnZero(queue, grid)
      }
    }
  }
  return count
}
function turnZero(queue, grid) {
  const dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]]
  while (queue.length) {
    const cur = queue.shift()
    for (const dir of dirs) {
      const x = cur[0] + dir[0]
      const y = cur[1] + dir[1]
      if (x < 0 || x >= grid.length || y < 0 || y >= grid[0].length || grid[x][y] !== '1') {
        continue
      }
      grid[x][y] = '0'
      queue.push([x, y])
    }
  }
}

Notes:

  1. Count + 1 when encountering 1
    Maintain a queue and list its coordinates when it encounters 1
    The node is out of the column, and four directions are investigated. If it is 1, it is changed to 0, and the node is listed
    If the boundary is exceeded or 0 is encountered, skip and do not enter the column
    List out... List in... Until there is no node that can be listed, all 1s of the current island will be turned to 0
  2. A this line is in the first line, and a the children enter the line when they leave the line

Problem solving three parallel search set

class UnionFind {
    constructor(n) { //Construct a set with n nodes
        this.count = n //Total number of concurrent search sets
        this.parent = new Array(n)
        this.size = new Array(n)  // The size array records the weight of each tree
        for (let i = 0; i < n; i++) {
            this.parent[i] = i; // You are your own parent
            this.size[i] = 1;	//Number of nodes on each collection
        }
    }

    union(p, q) { //Connected node p and node q, p and q are indexes
        let rootP = this.find(p);
        let rootQ = this.find(q);
        if (rootP === rootQ) return
        // A small number of elements are connected to a large number of elements, which is more balanced
        if (this.size[rootP] > this.size[rootQ]) {
            this.parent[rootQ] = rootP;
            this.size[rootP] += this.size[rootQ];
        } else {
            this.parent[rootP] = rootQ;
            this.size[rootQ] += this.size[rootP];
        }
        this.count--;
    }

    isConnected(p, q) { //Judge whether P and Q are connected
        return this.find(p) === this.find(q)
    }

    find(x) { //Find the root of node x
        while (this.parent[x] != x) {
            // Path compression
            this.parent[x] = this.parent[this.parent[x]];
            x = this.parent[x];
        }
        return x;
    }

    getCount() { //Returns the number of subsets
        return this.count;
    }

}

var numIslands = function (grid) {
    let m = grid.length
    if (m === 0) return 0
    let n = grid[0].length
    const dummy = -1
    const dirs = [[1, 0], [0, 1]]//Direction array right down
    const uf = new UnionFind(m * n)
    for (let x = 0; x < m; x++) {
        for (let y = 0; y < n; y++)
            if (grid[x][y] === '0') {//If the mesh is 0, merge with dummy
                uf.union(n * x + y, dummy) 
            }
            else if (grid[x][y] === '1') {//If the grid is 1, try down to the right
                for (let d of dirs) {
                    let r = x + d[0]
                    let c = y + d[1]
                    if (r >= m || c >= n) continue //Coordinate legitimacy
                    if (grid[r][c] === '1') { //If 1 is below the right side of the current grid, it will be merged with the current grid
                        uf.union(n * x + y, n * r + c)
                    }
                }
            }
    }
    return uf.getCount()  //Return and query the number of sets minus one
};

Notes:

  1. All 0's are fixed and merged, and the last count is reduced by one

Keywords: Algorithm Graph Theory

Added by quetz67 on Thu, 03 Feb 2022 16:16:38 +0200