题目:

假设你设计一个游戏,用一个 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的更多相关文章

  1. Leetcode之深度优先搜索(DFS)专题-200. 岛屿数量(Number of Islands)

    Leetcode之深度优先搜索(DFS)专题-200. 岛屿数量(Number of Islands) 深度优先搜索的解题详细介绍,点击 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计 ...

  2. LeetCode 200:岛屿数量 Number of Islands

    题目: 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. Given ...

  3. Leetcode题目200.岛屿数量(BFS+DFS+并查集-中等)

    题目描述: 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 ...

  4. Java实现 LeetCode 200 岛屿数量

    200. 岛屿数量 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. ...

  5. 力扣Leetcode 200. 岛屿数量

    岛屿数量 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量. 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成. 此外,你可以假设该网 ...

  6. [LeetCode]695. 岛屿的最大面积(DFS/BFS)、200. 岛屿数量(DFS/BFS待做/并差集待做)

    695. 岛屿的最大面积 题目 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被 ...

  7. [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 ...

  8. DFS或BFS(深度优先搜索或广度优先搜索遍历无向图)-04-无向图-岛屿数量

    给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 1: 输入: ...

  9. LeetCode 200. 岛屿数量

    习题地址 https://leetcode-cn.com/problems/number-of-islands/ 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水 ...

随机推荐

  1. python基础入门之四 —— 列表

    1.格式 [数据1,数据2,数据3,...] 列表可以一次性存多个数据,可以为不同的数据类型 2.下标 从0开始循序向下分配 3.常用函数 查找 index():返回指定数据所在位置下标,不存在就报错 ...

  2. cesium结合geoserver利用WFS服务实现图层新增(附源码下载)

    前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. 内 ...

  3. 检测APK是否存在Janus漏洞步骤

    Janus说明   Android APP仅使用V1签名,可能存在Janus漏洞(CVE-2017-13156),Janus漏洞(CVE-2017-13156)允许攻击者在不改变原签名的情况下任意修改 ...

  4. IDEA 修改编码

    IDEA: 一. 文件编码修改 IntelliJ IDEA可以在菜单中的File -> Settings -> Editor -> File Encoding下修改项目文件的编码 1 ...

  5. Python之基础、细节

    引号的用法 单引号对 ' ' :表示字符串,可以换行 双引号对 " " :表示字符串 三引号对 ''' ''' 和 """ ""& ...

  6. OSI七层协议大白话解读

    参考链接:https://www.cnblogs.com/zx125/p/11295985.html 国际标准化组织(ISO)制定了osi七层模型,iso规定了各种各样的协议,并且分了7层 应用层 应 ...

  7. Python 静态类型检查 mypy 示例

    以下所有例子都参考了最新版本的 Python 文档与 mypy 文档 必备条件 安装最新版本的 Python 和 mypy 要学会按需配置自己的编辑器,比如我的 VSCode 就装好了 Python ...

  8. PostgreSQL内核学习笔记十一(索引)

    Index Scan涉及到两部分的内容Heap Only Tuple和index-only-scan. 什么是Heap Only Tuple(HOT)? 例如:Update a Row Without ...

  9. opencv —— morphologyEx 开运算、闭运算、形态学梯度、顶帽、黑帽

    开运算:先腐蚀后膨胀. 能够排除小亮点. 闭运算:先膨胀后腐蚀. 能够排除小黑点. 形态学梯度:膨胀图 — 腐蚀图. 对二值图像进行这一操作,可将图块的边缘突出出来,故可用来保留物体边缘轮廓. 顶帽: ...

  10. java控制台模式控制光标及字符颜色

    System.out.println("\033[47;31mhello world\033[5m"); 47是字背景颜色, 31是字体的颜色, hello world是字符串.  ...