Leetcode(934)——最短的桥

题目

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

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

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

示例 1:

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

示例 2:

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

示例 3:

输入:A = [[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

提示:

  • 222 <= A.length == A[0].length <= 100100100
  • A[i][j] == 000 或 A[i][j] == 111

题解

方法一:DFS 修改值 + BFS

思路

​​  先找到其中一个岛屿中的一个点,然后进行 DFS\texttt{DFS}DFS 或 BFS\texttt{BFS}BFS,并把遍历到的所有值为 1 的点都变成 222,在遍历岛的过程中将 -1 岛的沿海一格全部加入队列。该队列就存储了 -1 岛的所有1格沿海。
​​  然后使用该队列进行 BFS\texttt{BFS}BFS,同时把遍历到的点 0 变成 -1,并且记录遍历的步数。当填海后要加入下一个点时,如果碰到的是 111 ,则返回 minminmin(最短桥的长度)。

​​  因为我们从 -1 岛的海岸线开始进行广度优先搜索(一层为一条海岸线),当它们到达了 1 岛中的任意一个位置时,增加的海岸线长度层数,即搜索层次就是答案。

注意:先导入再填海会导致出现两个的岛格可能会导入相同的海格,比如:[−1,0,−1][-1, 0, -1][−1,0,−1] 这会导致大量重复海格进入队列。

代码实现

Leetcode 官方题解:

class Solution {public:vector<int> direction{-1, 0, 1, 0, -1};// 主函数int shortestBridge(vector<vector<int>>& grid) {int m = grid.size(), n = grid[0].size();queue<pair<int, int>> points;// dfs寻找第一个岛屿,并把1全部赋值为2bool flipped = false;for (int i = 0; i < m; ++i) {if (flipped) break;for (int j = 0; j < n; ++j) {if (grid[i][j] == 1) {dfs(points, grid, m, n, i, j);flipped = true;break;}}}// bfs寻找第二个岛屿,并把过程中经过的0赋值为2int x, y;int level = 0;while (!points.empty()){++level;int n_points = points.size();while (n_points--) {auto [r, c] = points.front();points.pop();for (int k = 0; k < 4; ++k) {x = r + direction[k], y = c + direction[k+1];if (x >= 0 && y >= 0 && x < m && y < n) {if (grid[x][y] == 2) {continue;}   if (grid[x][y] == 1) {return level;}points.push({x, y});grid[x][y] = 2;}}}}return 0;}// 辅函数void dfs(queue<pair<int, int>>& points, vector<vector<int>>& grid, int m, int n, int i, int 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(points, grid, m, n, i - 1, j);dfs(points, grid, m, n, i + 1, j);dfs(points, grid, m, n, i, j - 1);dfs(points, grid, m, n, i, j + 1);}
};

我自己的:

class Solution {vector<int> direction{-1, 0, 1, 0, -1};int BFS(vector<vector<int>>& grid, queue<pair<int, int>>& q){int row, col, nextr, nextc, min = 0, times;while(!q.empty()){min++;  // 答案至少是 1times = q.size();while(times--){row = q.front().first;col = q.front().second;q.pop();grid[row][col] = -1;    // 填海for(int n = 0; n < 4; n++){nextr = row + direction[n];nextc = col + direction[n+1];if(nextr < 0 || nextr >= grid.size() || nextc < 0 || nextc >= grid[0].size())continue;// 先导入再填海会导致出现两个的岛格可能会导入相同的海格,比如:[-1, 0, -1] 这会导致大量重复海格进入队列if(grid[nextr][nextc] == 0)q.push(make_pair(nextr, nextc));else if(grid[nextr][nextc] == 1)return min;}}}return 0;}void DFS(vector<vector<int>>& grid, queue<pair<int, int>>& q, int row, int col){if(row < 0 || row >= grid.size() || col < 0 || col >= grid[0].size())return;if(grid[row][col] == 1){grid[row][col] = -1;DFS(grid, q, row+1, col);DFS(grid, q, row-1, col);DFS(grid, q, row, col+1);DFS(grid, q, row, col-1);}else if(grid[row][col] == 0) q.push(make_pair(row, col));  // 保存 -1 岛的一格沿海}
public:int shortestBridge(vector<vector<int>>& grid) {// 有且只有两座岛,返回必须翻转的 0 的最小数目,可以保证答案至少是 1// 分别标记两个岛,即一个岛为1,另二个岛为-1,海为0// 只需要遍历一个岛然后将其修改为-1,而另一个不需要遍历修改,则可以区分它们int row, col;queue<pair<int, int>> q;    // 保存 -1 岛的所有格子for(row = 0; row < grid.size(); row++){for(col = 0; col < grid[0].size(); col++){if(grid[row][col] == 1){DFS(grid, q, row, col);break;}}if(col < grid[0].size()) break;}// 从 -1 岛进行 BFSreturn BFS(grid, q);}
};

我自己的(改进——修改逻辑—— BFS 时先填海再查找导入):


class Solution {vector<int> direction{-1, 0, 1, 0, -1};int BFS(vector<vector<int>>& grid, queue<pair<int, int>>& q){int row, col, nextr, nextc, min = 0, times;while(!q.empty()){min++;  // 答案至少是 1times = q.size();while(times--){row = q.front().first;col = q.front().second;q.pop();for(int n = 0; n < 4; n++){nextr = row + direction[n];nextc = col + direction[n+1];if(nextr < 0 || nextr >= grid.size() || nextc < 0 || nextc >= grid[0].size())continue;if(grid[nextr][nextc] == 0){grid[nextr][nextc] = -1;    // 填海q.push(make_pair(nextr, nextc));}else if(grid[nextr][nextc] == 1)return min;}}}return 0;}void DFS(vector<vector<int>>& grid, queue<pair<int, int>>& q, int row, int col){if(row < 0 || row >= grid.size() || col < 0 || col >= grid[0].size())return;if(grid[row][col] == 1){grid[row][col] = -1;DFS(grid, q, row+1, col);DFS(grid, q, row-1, col);DFS(grid, q, row, col+1);DFS(grid, q, row, col-1);}else if(grid[row][col] == 0){grid[row][col] = -1;    // 填海q.push(make_pair(row, col));  // 保存 -1 岛的一格沿海}}
public:int shortestBridge(vector<vector<int>>& grid) {// 有且只有两座岛,返回必须翻转的 0 的最小数目,可以保证答案至少是 1// 分别标记两个岛,即一个岛为1,另二个岛为-1,海为0// 只需要遍历一个岛然后将其修改为-1,而另一个不需要遍历修改,则可以区分它们int row, col;queue<pair<int, int>> q;    // 保存 -1 岛的所有格子for(row = 0; row < grid.size(); row++){for(col = 0; col < grid[0].size(); col++){if(grid[row][col] == 1){DFS(grid, q, row, col);break;}}if(col < grid[0].size()) break;}// 从 -1 岛进行 BFSreturn BFS(grid, q);}
};

复杂度分析

  • 时间复杂度:O(MN)O(MN)O(MN),其中 MMM 和 NNN 分别是数组 gridgridgrid 的行数和列数。
  • 空间复杂度:O(MN)O(MN)O(MN)。

Leetcode(934)——最短的桥相关推荐

  1. LeetCode 934. 最短的桥(2次BFS)

    1. 题目 在给定的二维二进制数组 A 中,存在两座岛.(岛是由四面相连的 1 形成的一个最大组.) 现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛. 返回必须翻转的 0 的最小数目. ...

  2. LeetCode 934 最短的桥

    题目描述 在给定的二维二进制数组 A 中,存在两座岛.(岛是由四面相连的 1 形成的一个最大 组.)现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛.返回必须翻转的 0 的最小数目.(可 ...

  3. 【LeetCode】934. 最短的桥

    题目 934. 最短的桥 给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域. 岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连.grid ...

  4. 【934. 最短的桥】

    来源:力扣(LeetCode) 描述:   给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域.   岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其 ...

  5. Leetcode最短的桥

    934. 最短的桥 思路:先通过任意搜索方法找到其中一个岛屿 然后利用广度优先搜索,查找其与另一个岛屿的最短距离. class Solution {public:vector<int> d ...

  6. LeetCode 244. 最短单词距离 II(哈希map+set二分查找)

    文章目录 1. 题目 2. 解题 2.1 暴力超时 2.2 哈希表+set二分查找 1. 题目 请设计一个类,使该类的构造函数能够接收一个单词列表. 然后再实现一个方法,该方法能够分别接收两个单词 w ...

  7. LeetCode 245. 最短单词距离 III

    文章目录 1. 题目 2. 解题 1. 题目 给定一个单词列表和两个单词 word1 和 word2,返回列表中这两个单词之间的最短距离. word1 和 word2 是有可能相同的,并且它们将分别表 ...

  8. LeetCode 243. 最短单词距离

    文章目录 1. 题目 2. 解题 1. 题目 给定一个单词列表和两个单词 word1 和 word2,返回列表中这两个单词之间的最短距离. 示例: 假设 words = ["practice ...

  9. LeetCode 581. 最短无序连续子数组(Shortest Unsorted Continuous Subarray)

    581. 最短无序连续子数组 581. Shortest Unsorted Continuous Subarray 题目描述 给定一个整型数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序 ...

  10. LeetCode 214. 最短回文串(字符串哈希)

    文章目录 1. 题目 2. 解题 1. 题目 给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串. 找到并返回可以用这种方式转换的最短回文串. 示例 1: 输入: "aace ...

最新文章

  1. 如何将txt格式的数据导入到MATLAB中,并绘制图线
  2. 数据中心用多模光纤技术及发展趋势
  3. Python访问MySQL
  4. 基于各种基础数据结构的SPFA和各种优化
  5. 【数据竞赛】Kaggle竞赛宝典国内外竞赛方案汇总
  6. docker下gitlab安装配置使用(完整版)
  7. 数据库开启了闪回和归档,关闭归档日志alter database noarchivelog的时候报错:ORA-38781: cannot disable media recovery
  8. PHP数组的使用方法小结
  9. 怎么从apk源码中查看服务器地址,反编译apk查看源码
  10. 太宰治《人间失格》经典语录20句,句句引人深思
  11. Ran 0 tests in 0.000s
  12. 如何批量将 Txt 文本文件转换为 jpeg、png、bmp 图片
  13. 操作系统——内核雏形
  14. c语言调用calculate函数,关于c语言中int calculate函数求解。谢谢
  15. 19/7/22 一个由王者荣耀引发的“惨案”(.NET)
  16. Java基础Day01-Java基础语法
  17. 计算机模拟超光速,世界75亿人口,全部堆积在一起有多高?电脑的模拟画面曝光...
  18. 艰难学习codepen之landscape
  19. php基础 正则表达式,PHP基础 —— 正则表达式
  20. 利用python库stats进行t检验

热门文章

  1. 自动控制原理专业词汇中英文对照(一)
  2. FontLab VI(字体制作软件)v6.1.4.7043中文版
  3. JavaScript中canvas绘制太极图案
  4. php 手写签批 手机办公_好签原笔迹手写签批SDK
  5. 限制计算机用户使用指定软件,电脑使用时间限制软件(Time Boss)
  6. 手写RPC(五) 核心模块网络协议模块编写 ---- 自定义协议
  7. 松下服务器分频器输出信号与,详解几款常用分频器及音箱分频器电路图
  8. 述职答辩提问环节一般可以问些什么_2.50 述职报告与评审提问注意事项
  9. php获取文件名和后缀名
  10. linux date 4 2,JZ2440 linux-3.4.2内核启动报错:Verifying Checksum ... Bad Data CRC(示例代码)...