算法:最短的桥

举报
掘金安东尼 发表于 2022/10/25 10:47:21 2022/10/25
【摘要】 题目给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。你可以将任意数量的 0 变为 1 ,以使两座岛连接起来,变成 一座岛 。返回必须翻转的 0 的最小数目。示例 1:输入:grid = [[0,1],[1,0]]输出:1示例 2:输入:grid...

image.png

题目

给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。

岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。

你可以将任意数量的 0 变为 1 ,以使两座岛连接起来,变成 一座岛 。

返回必须翻转的 0 的最小数目。

示例 1:

输入:grid = [[0,1],[1,0]]
输出:1

示例 2:

输入:grid = [[0,1,0],[0,0,0],[0,0,1]]
输出:2

示例 3:

输入:grid = [[1,1,1,1,1],[1,0,0,0,1],[1,0,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]
输出:1
 

提示:

n == grid.length == grid[i].length
2 <= n <= 100
grid[i][j]01
grid 中恰有两个岛
通过次数41,814提交次数8

题解

解题思路
深入理解一下题目意思,现在有两座岛屿,现在要把两座岛变成一座岛

怎么样把两座岛变成一座岛呢

先使用DFS找到里面的一座岛屿,并且把岛屿里面所有的坐标都加入到队列中

再使用BFS从刚刚找到的岛屿中的点出去扩散去找最近的坐标为1也就是陆地的节点

第2步之所以用BFS是因为寻找最近路径使用BFS是最快的,当我们找到最近的陆地节点就可以直接退回了(这个时候其实我们已经知道走过的最短距离自然就知道需要翻转的最小数目)

function shortestBridge(grid) {
  const rows = grid.length;
  const cols = grid[0].length;
  // 方向数组
  const directions = [
    [0, 1],
    [0, -1],
    [1, 0],
    [-1, 0],
  ];
  const queue = [];
  const dfs = (i, j) => {
    // 1代表陆地  岛是由四面相连的 1 形成的一个最大组
    if (i < 0 || i >= rows || j < 0 || j >= cols || grid[i][j] !== 1) return;
    // 标记小岛2
    grid[i][j] = 2;
    // 初始化queue(记录小岛2的坐标)
    queue.push([i, j]);
    for (let [x, y] of directions) {
      dfs(i + x, j + y);
    }
  };
  const bfs = () => {
    let step = 0;
    while (queue.length) {
      let size = queue.length;
      step++;
      while (size--) {
        const [i, j] = queue.shift();
        // 出队列向四周扩散
        for (let [x, y] of directions) {
          const newI = i + x;
          const newJ = j + y;
          if (newI >= 0 && newI < rows && newJ >= 0 && newJ < cols) {
            // 找到小岛1,直接返回
            // 找到空白,继续前进搜寻
            if (grid[newI][newJ] === 1) {
              return step - 1;
            } else if (grid[newI][newJ] === 0) {
              // 先把它融入小岛1中避免重复访问到
              grid[newI][newJ] = 2;
              queue.push([newI, newJ]);
            }
          }
        }
      }
    }
  };
  // 标记小岛2 之所以用dfs是需要把当前岛上所有的陆地都遍历到并且加入队列
  for (let i = 0; i < rows; i++) {
    for (let j = 0; j < cols; j++) {
      // 从任一一个陆地节点出发去找到它所在的岛屿,
      if (grid[i][j] === 1) {
        dfs(i, j);
        return bfs();
      }
    }
  }
  return -1;
}
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。