200-岛屿数量

题目

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:grid = [
[“1”,“1”,“1”,“1”,“0”],
[“1”,“1”,“0”,“1”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“0”,“0”,“0”]
]
输出:1
示例 2:

输入:grid = [
[“1”,“1”,“0”,“0”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“1”,“0”,“0”],
[“0”,“0”,“0”,“1”,“1”]
]
输出:3

题解一 dfs

var numIslands = function(grid) {
  function dfs(grid,i,j){//格式!
    // 递归终止条件
    if(i<0||i>=grid.length||j<0||j>=grid[0].length||grid[i][j]==='0'){
       return  
    }
    grid[i][j]='0' // 走过的标记为0 两个中括号😂
    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
};

笔记:

  1. void traverse(TreeNode root) {
        // 判断 base case
        if (root == null) {
            return;
        }
        // 访问两个相邻结点:左子结点、右子结点
        traverse(root.left);
        traverse(root.right);
    }
    //dfs框架
    
  2. 如何避免这样的重复遍历呢?答案是标记已经遍历过的格子。以岛屿问题为例,我们需要在所有值为 1 的陆地格子上做 DFS 遍历。每走过一个陆地格子,就把格子的值改为 2,这样当我们遇到 2 的时候,就知道这是遍历过的格子了。也就是说,每个格子可能取三个值:

    0 —— 海洋格子
    1 —— 陆地格子(未遍历过)
    2 —— 陆地格子(已遍历过)

  3. 如果不把与它和同在一个岛的土地变成 0,则DFS遍历到它们时,会对一个岛重复计数

  4. 怎么找出同处一岛的所有 1
    DFS,以当前 1 为入口
    DFS 做的事情:
    将当前的 1 变 0
    当前坐标的上下左右依次递归,同处一个岛的 1 都变 0
    dfs 出口:超出矩阵边界,或遇到 0。不用沉岛,直接返回

题解二 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' // 做标记,避免重复遍历
        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])
    }
  }
}

笔记:

  1. 遇到 1 就计数 +1
    维护一个队列,遇到 1 就让它的坐标入列
    节点出列,并考察四个方向,如果是 1,将它转为 0,并将节点入列
    如果越界了或遇到 0 ,则跳过不用入列
    出列…入列…直到没有可以入列的节点,则当前岛屿的所有 1 都转 0 了
  2. a这一排先进队列,a出队时孩子进队

题解三 并查集

class UnionFind {
    constructor(n) { //构造一个节点数为n的集合
        this.count = n //并查集总数
        this.parent = new Array(n)
        this.size = new Array(n)  // size数组记录着每棵树的重量
        for (let i = 0; i < n; i++) {
            this.parent[i] = i; // 自己是自己的parent
            this.size[i] = 1;	//每个集合上节点的数量
        }
    }

    union(p, q) { //连通结点p和结点q, p和q都是索引
        let rootP = this.find(p);
        let rootQ = this.find(q);
        if (rootP === rootQ) return
        // 元素数量小的接到数量多的下面,这样比较平衡
        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) { //判断p,q是否连通
        return this.find(p) === this.find(q)
    }

    find(x) { //找到x结点的root
        while (this.parent[x] != x) {
            // 进行路径压缩
            this.parent[x] = this.parent[this.parent[x]];
            x = this.parent[x];
        }
        return x;
    }

    getCount() { //返回子集个数
        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]]//方向数组 向右 向下
    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') {//如果网格是0,则和dummy合并
                uf.union(n * x + y, dummy) 
            }
            else if (grid[x][y] === '1') {//如果网格是1,则向右 向下尝试
                for (let d of dirs) {
                    let r = x + d[0]
                    let c = y + d[1]
                    if (r >= m || c >= n) continue //坐标合法性
                    if (grid[r][c] === '1') { //当前网格的右边 下面如果是1,则和当前网格合并
                        uf.union(n * x + y, n * r + c)
                    }
                }
            }
    }
    return uf.getCount()  //返回并查集的个数减一就行
};

笔记:

  1. 所有的0固定合并,最后count减一个
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
矩阵岛屿是一个常见的计算机算法问题,通常用于解决图论和搜索相关的问题。在Python中,我们可以使用深度优先搜索(DFS)算法来解决矩阵岛屿问题。 首先,我们需要将矩阵表示为一个二维数组。每个元素可以通过0或1来表示,其中0表示水域,1表示陆地。我们需要遍历整个二维数组,当遇到1(表示陆地)时,就进行DFS搜索,找到与当前陆地相邻的所有陆地,将其标记为已访问,并继续搜索相邻的陆地。通过这样的遍历和搜索,我们可以计算出矩阵中的岛屿数量。 下面是一个简单的Python实现示例: ```python def dfs(grid, i, j): # 判断当前坐标是否越界或者已经访问过 if i < 0 or i >= len(grid) or j < 0 or j >= len(grid[0]) or grid[i][j] != 1: return # 标记当前坐标为已访问 grid[i][j] = '#' # 搜索上下左右四个方向 dfs(grid, i - 1, j) dfs(grid, i + 1, j) dfs(grid, i, j - 1) dfs(grid, i, j + 1) def numIslands(grid): count = 0 for i in range(len(grid)): for j in range(len(grid[0])): if grid[i][j] == 1: # 发现一个新的岛屿,进行DFS搜索 dfs(grid, i, j) count += 1 return count # 示例输入 grid = [ [1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 1] ] # 调用函数计算岛屿数量 islands = numIslands(grid) print("岛屿数量为:", islands) ``` 运行上述代码,输出结果为:岛屿数量为:3。表示给定的矩阵中有3个岛屿。这就是通过深度优先搜索算法来解决矩阵岛屿问题的一个简单实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

codrab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值