434. 岛屿的个数II
给定 n,m,分别代表一个2D矩阵的行数和列数,同时,给定一个大小为 k 的二元数组A。起初,2D矩阵的行数和列数均为 0,即该矩阵中只有海洋。二元数组有 k 个运算符,每个运算符有 2 个整数 A[i].x, A[i].y,你可通过改变矩阵网格中的A[i].x],[A[i].y] 来将其由海洋改为岛屿。请在每次运算后,返回矩阵中岛屿的数量。
注意事项
0 代表海,1 代表岛。如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。
样例
给定 n
= 3
, m
= 3
, 二元数组 A = [(0,0),(0,1),(2,2),(2,1)]
.
返回 [1,1,2,2]
.
这题用到了类似并查集的思路,题目不算难,但自己给自己挖了个大坑:
x = parent[x][y].x;
y = parent[x][y].y;
还有set并不是很方便,改一改是可以不用的。
在查找root的过程中可以进行压缩路径,将父节点指向上一级的指针设置为祖父节点指向的上一级指针,可以大幅减少查找时的时间开销。
主要思路是将新增岛屿的root设为自己,将上下左右四个方向连接的岛屿(如果有)的root->root指向自己,每次操作必定使(最多)五块岛屿合为一个,用1减去操作之前四周岛屿的不同root数量即为岛屿数变化量。也可在在周围四块岛屿查找root结束时判断root是否指向新增岛屿,若不是则岛屿数量-1。参考https://www.cnblogs.com/grandyang/p/5190419.html,这种方法不用进行岛屿查重,会方便很多。
给定 n,m,分别代表一个2D矩阵的行数和列数,同时,给定一个大小为 k 的二元数组A。起初,2D矩阵的行数和列数均为 0,即该矩阵中只有海洋。二元数组有 k 个运算符,每个运算符有 2 个整数 A[i].x, A[i].y,你可通过改变矩阵网格中的A[i].x],[A[i].y] 来将其由海洋改为岛屿。请在每次运算后,返回矩阵中岛屿的数量。
注意事项
0 代表海,1 代表岛。如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。
给定 n
= 3
, m
= 3
, 二元数组 A = [(0,0),(0,1),(2,2),(2,1)]
.
返回 [1,1,2,2]
.
这题用到了类似并查集的思路,题目不算难,但自己给自己挖了个大坑:
x = parent[x][y].x;
y = parent[x][y].y;
还有set并不是很方便,改一改是可以不用的。
在查找root的过程中可以进行压缩路径,将父节点指向上一级的指针设置为祖父节点指向的上一级指针,可以大幅减少查找时的时间开销。
主要思路是将新增岛屿的root设为自己,将上下左右四个方向连接的岛屿(如果有)的root->root指向自己,每次操作必定使(最多)五块岛屿合为一个,用1减去操作之前四周岛屿的不同root数量即为岛屿数变化量。也可在在周围四块岛屿查找root结束时判断root是否指向新增岛屿,若不是则岛屿数量-1。参考https://www.cnblogs.com/grandyang/p/5190419.html,这种方法不用进行岛屿查重,会方便很多。
struct NPoint {
int x;
int y;
NPoint() : x(-1), y(-1) {}
NPoint(int a, int b) : x(a), y(b) {}
NPoint(Point& a) : x(a.x), y(a.y) {}
bool operator < (const NPoint &a) const
{
if (this->x == a.x && this->y == a.y)
return false;
else {
if (this->y != a.y)
return this->y > a.y;
else
return this->x > a.x;
}
}
};
class Solution {
public:
/*
* @param n: An integer
* @param m: An integer
* @param operators: an array of point
* @return: an integer array
*/
vector<int> numIslands2(int n, int m, vector<Point> &operators) {
// write your code here
int count = 0;
vector<int> result;
vector<vector<int>> map(n, vector<int>(m));
vector<vector<NPoint>> parent(n, vector<NPoint>(m));
auto getroot = [&](int x, int y) {
while (parent[x][y].x != x || parent[x][y].y != y) {
//x = parent[x][y].x;//注意
//y = parent[x][y].y;
int xtmp = parent[x][y].x;
int ytmp = parent[x][y].y;
parent[x][y].x=parent[xtmp][ytmp].x;
parent[x][y].y=parent[xtmp][ytmp].y;
y = ytmp;
x = xtmp;
}
return NPoint(x, y);
};
for (Point& p : operators) {
if (map[p.x][p.y] == 1) {
result.push_back(count);
continue;
}
if (map[p.x][p.y] == 0) {
vector<NPoint> ps;
if (p.x>0)
if (map[p.x - 1][p.y] == 1) ps.push_back(NPoint(p.x - 1, p.y));
if (p.y>0)
if (map[p.x][p.y - 1] == 1) ps.push_back(NPoint(p.x, p.y - 1));
if (p.x<n - 1)
if (map[p.x + 1][p.y] == 1) ps.push_back(NPoint(p.x + 1, p.y));
if (p.y<m - 1)
if (map[p.x][p.y + 1] == 1) ps.push_back(NPoint(p.x, p.y + 1));
set<NPoint> num;
for (NPoint point : ps) {
num.insert(getroot(point.x, point.y));
}
int n1 = num.size();
for (NPoint point : num) {
parent[point.x][point.y] = NPoint(p.x, p.y);
}
ps.push_back(p);
map[p.x][p.y] = 1;
parent[p.x][p.y]=NPoint(p.x,p.y);
count += 1 - n1;
result.push_back(count);
}
}
return result;
}
};