LeetCode 934. 最短的桥 --javascript BFS

315 阅读2分钟

934. 最短的桥

描述

在给定的二维二进制数组 A 中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组。)

现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛。

返回必须翻转的 0 的最小数目。(可以保证答案至少是 1 。)

image.png

题解

广度优先搜索(breadth-first search,BFS)不同与深度优先搜索,它是一层层进行遍历的,因 此需要用先入先出的队列而非先入后出的栈进行遍历。由于是按层次进行遍历,广度优先搜索时 按照“广”的方向进行遍历的,也常常用来处理最短路径等问题。

目前这道题很明显这是在求两个岛屿间的最短距离。 步骤: 1、任意搜索方法找到其中一个岛 2、利用广度优先搜索,查找其与另一个岛屿的最短距离,用先入先出的队列按层次进行遍历递进。

第一种方法借助了额外的空间消耗,复杂度相同的情况下,这是不大好的,然后第二种方法做了小优化。

coding

// /**
//  * @param {number[][]} grid
//  * @return {number}
//  */

// var shortestBridge = function(grid) {
//  let m = grid.length, n = grid[0].length;
//  let level = 0;
//  let curpoints = [];
//  const points = [];

// function dfs(i , j) {
//     if(i < 0 || j < 0 || i === m || j === n || grid[i][j] === 2) return;
//     if(grid[i][j] === 0){
//         points.push([i, j]);
//         return;
//     }
//     grid[i][j] = 2;
//     dfs(i - 1, j);
//     dfs(i + 1, j);
//     dfs(i, j - 1);
//     dfs(i, j + 1);
// }
// // 寻找第一座岛屿
// for(let i = 0; i < m; ++ i) {
//    if(grid[i].includes(1)){
//        dfs(i, grid[i].indexOf(1));
//        break;
//    }
// }
//  // bfs 寻找第二个岛屿, 并且把经过的0赋值为2
//  while(points.length) {
//      const [i, j] = points.shift();
//     if(i < 0 || j < 0 || i >= m || j >= n || grid[i][j] === 2) {
//       uplateLen();
//       continue;
//     }
//      if (grid[i][j] === 1) { // 扩张到另一岛屿时,桥梁建成
//       break;
//     }
//     if (grid[i][j] === 0) { // 存储下一轮扩张的坐标
//       curpoints.push([i - 1, j], [i + 1, j], [i, j - 1], [i, j + 1]);
//     }
//     grid[i][j] = 2;
//     uplateLen()
//  }
//   function uplateLen() {
//     if(!points.length) {
//         level++;
//         points.push(...curpoints);
//         curpoints = [];
//     }
// }
// return level;
// };

/**
 * @param {number[][]} grid
 * @return {number}
 */
const direction = [-1, 0, 1, 0, -1]
var shortestBridge = function(grid) {
 let m = grid.length, n = grid[0].length;
 const points = [];
// 寻找第一座岛屿
for(let i = 0; i < m; ++ i) {
   if(grid[i].includes(1)){
       dfs(grid, points, i, grid[i].indexOf(1), m, n);
       break;
   }
}
 // bfs 寻找第二个岛屿, 并且把经过的0赋值为2 
 let level = 0, dx, dy;
 while(points.length) {
     ++level;
     let n_points = points.length;
     while(n_points--) {
        const [i, j] = points.shift();
        for(let k = 0; k < 4; k++) {
            dx = i + direction[k];
            dy = j + direction[k+1];
            if(dx < 0 || dy < 0 || dx === m || dy === n || grid[dx][dy] === 2) {
              continue;
            }
            if (grid[dx][dy] === 1) { // 扩张到另一岛屿时,桥梁建成
               return level;
            }
            if (grid[dx][dy] === 0) { // 存储下一轮扩张的坐标
              points.push([dx, dy]);
            }
           grid[dx][dy] = 2; 
        }
     }
     
 }
return level;
};
// 辅助函数
function dfs(grid, points, i , j, m, n) {
    if(i < 0 || j < 0 || i === m || j === n || grid[i][j] === 2) return;
    if(grid[i][j] === 0){
        points.push([i, j]);
        return;
    }
    grid[i][j] = 2;
    dfs(grid, points, i - 1, j, m, n);
    dfs(grid, points, i + 1, j, m, n);
    dfs(grid, points, i, j - 1, m, n);
    dfs(grid, points, i, j + 1, m, n);
}