305. 岛屿数量 II
题目:
假设你设计一个游戏,用一个 m 行 n 列的 2D 网格来存储你的游戏地图。
起始的时候,每个格子的地形都被默认标记为「水」。我们可以通过使用 addLand 进行操作,将位置 (row, col) 的「水」变成「陆地」。
你将会被给定一个列表,来记录所有需要被操作的位置,然后你需要返回计算出来 每次 addLand 操作后岛屿的数量。
注意:一个岛的定义是被「水」包围的「陆地」,通过水平方向或者垂直方向上相邻的陆地连接而成。你可以假设地图网格的四边均被无边无际的「水」所包围。
请仔细阅读下方示例与解析,更加深入了解岛屿的判定。
示例:
输入: m = 3, n = 3, positions = [[0,0], [0,1], [1,2], [2,1]]
输出: [1,1,2,3]
解析:
起初,二维网格 grid 被全部注入「水」。(0 代表「水」,1 代表「陆地」)
0 0 0
0 0 0
0 0 0
操作 #1:addLand(0, 0) 将 grid[0][0] 的水变为陆地。
1 0 0
0 0 0 Number of islands = 1
0 0 0
操作 #2:addLand(0, 1) 将 grid[0][1] 的水变为陆地。
1 1 0
0 0 0 岛屿的数量为 1
0 0 0
操作 #3:addLand(1, 2) 将 grid[1][2] 的水变为陆地。
1 1 0
0 0 1 岛屿的数量为 2
0 0 0
操作 #4:addLand(2, 1) 将 grid[2][1] 的水变为陆地。
1 1 0
0 0 1 岛屿的数量为 3
0 1 0
拓展:
你是否能在 O(k log mn) 的时间复杂度程度内完成每次的计算?(k 表示 positions 的长度)
解答:
方法1:
首先我想到的就是dfs,每次加入陆地的时候考察一共有多少岛屿。但不能每次加入陆地都遍历全部矩阵,这样复杂度太高了,需要剪枝。
我的思路是这样:
每个独立的岛屿有独特的编号。每次addland的时候,遍历周边四个位置。
1.如果有一个相邻岛屿,岛屿数--,保存这个相邻岛屿的编号。
2.如果有第二个、甚至第三、四个相邻岛屿,就把之后的相邻的岛屿都用dfs遍历,全部更新为第一个相邻岛屿的编号。每次仍然记得总岛屿数--。
3.如果没有相邻岛屿,直接赋岛屿编号,全局的岛屿编号加一。
代码:
- class Solution {
- public:
- vector<vector<int>> d={{,-},{,},{,},{-,}};
- int m,n;
- bool check(int x,int y){
- if(x< or x>=m or y< or y>=n){
- return false;
- }
- return true;
- }
- vector<int> numIslands2(int m, int n, vector<vector<int>>& positions) {
- this->m=m;
- this->n=n;
- vector<vector<int>> matrix(m,vector<int>(n,));
- int val=;//下一个有效的岛屿编号
- vector<int>res(positions.size(),);
- res[]=;
- matrix[positions[][]][positions[][]]=val++;
- for(int i=;i<positions.size();++i){
- if(matrix[positions[i][]][positions[i][]]!=){//本身就是岛屿
- res[i]=res[i-];
- continue;
- }
- res[i]=res[i-]+;
- int x=positions[i][],y=positions[i][],cur_val=;
- // cout<<"addland "<<x<<" "<<y<<endl;
- for(int j=;j<;++j){
- int new_x=x+d[j][],new_y=y+d[j][];
- if(check(new_x,new_y) and matrix[new_x][new_y]!=cur_val){
- if(cur_val==){//相邻的第一片岛屿
- cur_val=matrix[new_x][new_y];
- res[i]--;
- }
- else if(matrix[new_x][new_y]!=){//相邻的第二/三/四片岛屿
- dfs(matrix,new_x,new_y,matrix[new_x][new_y],cur_val);
- res[i]--;
- }
- }
- }
- matrix[x][y]=cur_val==?val++:cur_val;
- // for(auto& vec:matrix){
- // for(int x:vec){
- // cout<<x<<" ";
- // }cout<<endl;
- // }
- }
- return res;
- }
- void dfs(vector<vector<int>>& matrix,int x,int y,int ori_val,int new_val){
- // cout<<"dfs: "<<x<<" "<<y<<" "<<ori_val<<" "<<new_val<<endl;
- //将ori_val改为new_val
- matrix[x][y]=new_val;
- int new_x,new_y;
- for(int i=;i<;++i){
- new_x=x+d[i][],new_y=y+d[i][];
- if(check(new_x,new_y) and matrix[new_x][new_y]==ori_val){
- dfs(matrix,new_x,new_y,ori_val,new_val);
- }
- }
- }
- };
方法2:
使用并差集。
代码:
- class Solution {
- public:
- vector<vector<int>> dif={{,},{,-},{,},{-,}};
- //并差集
- vector<int> parents;
- int islands = ;
- int getParent(int child){
- if(child!=parents[child]){
- parents[child]=getParent(parents[child]);
- }
- return parents[child];
- }
- void merge(int x, int y){
- int px = getParent(x);
- int py = getParent(y);
- if(px != py){
- parents[px] = py;
- islands--;
- }
- }
- vector<int> numIslands2(int m, int n, vector<vector<int>>& positions) {
- vector<int> res;
- parents.assign(m*n,-);
- for(auto& coordinate:positions){
- int row=coordinate[],col=coordinate[],index=row*n+col;
- if(parents[index]==-){//水
- ++islands;
- parents[index]=index;
- for(const auto& d:dif){
- int new_index=(row+d[])*n+col+d[];
- if(row+d[]<m and row+d[]>= and col+d[]<n and col+d[]>= and parents[new_index]!=-){
- merge(new_index,index);
- }
- }
- }
- res.push_back(islands);
- }
- return res;
- }
- };
305. 岛屿数量 II的更多相关文章
- Leetcode之深度优先搜索(DFS)专题-200. 岛屿数量(Number of Islands)
Leetcode之深度优先搜索(DFS)专题-200. 岛屿数量(Number of Islands) 深度优先搜索的解题详细介绍,点击 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计 ...
- LeetCode 200:岛屿数量 Number of Islands
题目: 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. Given ...
- Leetcode题目200.岛屿数量(BFS+DFS+并查集-中等)
题目描述: 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 ...
- Java实现 LeetCode 200 岛屿数量
200. 岛屿数量 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. ...
- 力扣Leetcode 200. 岛屿数量
岛屿数量 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量. 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成. 此外,你可以假设该网 ...
- [LeetCode]695. 岛屿的最大面积(DFS/BFS)、200. 岛屿数量(DFS/BFS待做/并差集待做)
695. 岛屿的最大面积 题目 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被 ...
- [LeetCode] 305. Number of Islands II 岛屿的数量 II
A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand oper ...
- DFS或BFS(深度优先搜索或广度优先搜索遍历无向图)-04-无向图-岛屿数量
给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 1: 输入: ...
- LeetCode 200. 岛屿数量
习题地址 https://leetcode-cn.com/problems/number-of-islands/ 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水 ...
随机推荐
- 数据算法 --hadoop/spark数据处理技巧 --(3.左外连接 4.反转排序)
三. 左外连接 考虑一家公司,比如亚马逊,它拥有超过2亿的用户,每天要完成数亿次交易.假设我们有两类数据,用户和交易: users(user_id,location_id) transactions( ...
- k8s系列--- dashboard认证及分级授权
http://blog.itpub.net/28916011/viewspace-2215214/ 因版本不一样,略有改动 Dashboard官方地址: https://github.com/kube ...
- LVS服务原理以及搭建
一.LVS简介 LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统,目的在于使用集群技术和Linux操作系统实现一个高性能.高可用的服务器.它 ...
- js—数组那些事儿
数组维度升级 创建一维数组 //创建一维数组 var a=[]; var b=new Array(); var c=[1,2,'w']; var d=[1,2,[1,2]]; 创建二维数组 var c ...
- SQL Server 2019 安装教程
SQL Server 2019 安装教程 下载安装SQL: 1.下载SQL Server 2019 Developer 官方网址:下载地址. 2.下拉选择免费版本,直接点击下载(别问,问就是家境贫寒
- 多线程共享变量和 AsyncLocal
>>返回<C# 并发编程> 1. 简介 2. 异步下的共享变量 3. 解析 AsyncLocal 3.1. IAsyncLocalValueMap 的实现 3.2. 结论 1. ...
- 避免XSS攻击
遭遇XSS攻击怎么解决 XSS的攻击手段 利用JavaScript或DOM方式进行攻击,XSS(脚本注入)提交,然后进行页面展示,影响页面的正常结构,还可以做钓鱼网站,来盗取用户的信息. 比如在页面评 ...
- Centos7下安装包方式安装MySQL
安装包下载地址:https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.27-1.el7.x86_64.rpm-bundle.tar 第一步:在 /h ...
- leetcode腾讯精选练习之旋转链表(四)
旋转链表 题目: 给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: 1->2->3->4->5->NULL, k = ...
- EasyUI笔记(三)Window窗口
本系列只列出一些常用的属性.事件或方法,具体完整知识请查看API文档 Window(窗口) 窗口控件是一个浮动和可拖拽的面板可以用作应用程序窗口.默认情况下,窗口可以移动,调整大小和关闭.它的内容也可 ...