Leetcode(934)——最短的桥
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)——最短的桥相关推荐
- LeetCode 934. 最短的桥(2次BFS)
1. 题目 在给定的二维二进制数组 A 中,存在两座岛.(岛是由四面相连的 1 形成的一个最大组.) 现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛. 返回必须翻转的 0 的最小数目. ...
- LeetCode 934 最短的桥
题目描述 在给定的二维二进制数组 A 中,存在两座岛.(岛是由四面相连的 1 形成的一个最大 组.)现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛.返回必须翻转的 0 的最小数目.(可 ...
- 【LeetCode】934. 最短的桥
题目 934. 最短的桥 给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域. 岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连.grid ...
- 【934. 最短的桥】
来源:力扣(LeetCode) 描述: 给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域. 岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其 ...
- Leetcode最短的桥
934. 最短的桥 思路:先通过任意搜索方法找到其中一个岛屿 然后利用广度优先搜索,查找其与另一个岛屿的最短距离. class Solution {public:vector<int> d ...
- LeetCode 244. 最短单词距离 II(哈希map+set二分查找)
文章目录 1. 题目 2. 解题 2.1 暴力超时 2.2 哈希表+set二分查找 1. 题目 请设计一个类,使该类的构造函数能够接收一个单词列表. 然后再实现一个方法,该方法能够分别接收两个单词 w ...
- LeetCode 245. 最短单词距离 III
文章目录 1. 题目 2. 解题 1. 题目 给定一个单词列表和两个单词 word1 和 word2,返回列表中这两个单词之间的最短距离. word1 和 word2 是有可能相同的,并且它们将分别表 ...
- LeetCode 243. 最短单词距离
文章目录 1. 题目 2. 解题 1. 题目 给定一个单词列表和两个单词 word1 和 word2,返回列表中这两个单词之间的最短距离. 示例: 假设 words = ["practice ...
- LeetCode 581. 最短无序连续子数组(Shortest Unsorted Continuous Subarray)
581. 最短无序连续子数组 581. Shortest Unsorted Continuous Subarray 题目描述 给定一个整型数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序 ...
- LeetCode 214. 最短回文串(字符串哈希)
文章目录 1. 题目 2. 解题 1. 题目 给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串. 找到并返回可以用这种方式转换的最短回文串. 示例 1: 输入: "aace ...
最新文章
- 如何将txt格式的数据导入到MATLAB中,并绘制图线
- 数据中心用多模光纤技术及发展趋势
- Python访问MySQL
- 基于各种基础数据结构的SPFA和各种优化
- 【数据竞赛】Kaggle竞赛宝典国内外竞赛方案汇总
- docker下gitlab安装配置使用(完整版)
- 数据库开启了闪回和归档,关闭归档日志alter database noarchivelog的时候报错:ORA-38781: cannot disable media recovery
- PHP数组的使用方法小结
- 怎么从apk源码中查看服务器地址,反编译apk查看源码
- 太宰治《人间失格》经典语录20句,句句引人深思
- Ran 0 tests in 0.000s
- 如何批量将 Txt 文本文件转换为 jpeg、png、bmp 图片
- 操作系统——内核雏形
- c语言调用calculate函数,关于c语言中int calculate函数求解。谢谢
- 19/7/22 一个由王者荣耀引发的“惨案”(.NET)
- Java基础Day01-Java基础语法
- 计算机模拟超光速,世界75亿人口,全部堆积在一起有多高?电脑的模拟画面曝光...
- 艰难学习codepen之landscape
- php基础 正则表达式,PHP基础 —— 正则表达式
- 利用python库stats进行t检验
热门文章
- 自动控制原理专业词汇中英文对照(一)
- FontLab VI(字体制作软件)v6.1.4.7043中文版
- JavaScript中canvas绘制太极图案
- php 手写签批 手机办公_好签原笔迹手写签批SDK
- 限制计算机用户使用指定软件,电脑使用时间限制软件(Time Boss)
- 手写RPC(五) 核心模块网络协议模块编写 ---- 自定义协议
- 松下服务器分频器输出信号与,详解几款常用分频器及音箱分频器电路图
- 述职答辩提问环节一般可以问些什么_2.50 述职报告与评审提问注意事项
- php获取文件名和后缀名
- linux date 4 2,JZ2440 linux-3.4.2内核启动报错:Verifying Checksum ... Bad Data CRC(示例代码)...