题目:
A 2d grid map of m rows and n columns
is initially filled with water. We may perform an addLand operation which turns the water at position (row, col) into a land. Given a list of positions to operate, count the number of islands after each addLand operation.
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example:
Given m = 3, n = 3, positions
= [[0,0], [0,1], [1,2], [2,1]].
Initially, the 2d grid grid is filled with water. (Assume 0 represents water and 1 represents
land).
0 0 0 0 0 0 0 0 0
Operation #1: addLand(0, 0) turns the water at grid[0][0] into a land.
1 0 0 0 0 0 Number of islands = 1 0 0 0
Operation #2: addLand(0, 1) turns the water at grid[0][1] into a land.
1 1 0 0 0 0 Number of islands = 1 0 0 0
Operation #3: addLand(1, 2) turns the water at grid[1][2] into a land.
1 1 0 0 0 1 Number of islands = 2 0 0 0
Operation #4: addLand(2, 1) turns the water at grid[2][1] into a land.
1 1 0 0 0 1 Number of islands = 3 0 1 0
We return the result as an array: [1, 1, 2, 3]
Challenge:
Can you do it in time complexity O(k log mn), where k is the length of the positions?
思路:
这是一道合并-查找题目(Union-Find)题目,这类题目的实现也具有一定套路,值得总结:
1)为每个位置初始化一个父结点。因为是一个二维数组,比较方便的做法是将二维数组映射到一维,我们采用的方法是将 (x, y) 的父结点映射到 (x * n + y)。
2)每次插入一个新元素时,查找其上下左右地图是不是有相邻的陆地(当然在此之前需要建立一张二维的地图,并随着插入新元素而不断更新该地图)。
3)默认情况下,新添加一个点小岛的数量就增加1,然而如果这个新添加的陆地有相邻的陆地,就需要将其合并成一块陆地,此时小岛数量减1。上下左右四个方向,每次合并一个邻接点,小岛的数量都要减1。
我觉得这里查找parents的代码比较关键,建议读者理解并且记下来。
代码:
class Solution {
public:
vector<int> numIslands2(int m, int n, vector<pair<int, int>>& positions) {
vector<vector<int>> island(m, vector<int>(n, 0));
vector<int> result;
int num = 0;
vector<int> parents(m * n); // record the root of each position using 1D array
for(int i = 0; i < m * n; ++i) {
parents[i] = i;
}
vector<pair<int, int>> directions{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for(auto val : positions) { // for each added island
for(auto val2 : directions) { // for each direction
int x = val.first, y = val.second;
int px = x + val2.first, py = y + val2.second;
if(px < 0 || px >= m || py < 0 || py >= n || island[px][py] == 0) {
continue;
}
// par1 is the central point, and par2 is the neighboring point, we map them to 1D array
int par1 = x * n + y, par2 = px * n + py;
while(par1 != parents[par1]) { // do not change anything, just reach to its ancester
parents[par1] = parents[parents[par1]];
par1 = parents[par1];
}
while(par2 != parents[par2]) { // do not change anything, just reach to its ancester
parents[par2] = parents[parents[par2]];
par2 = parents[par2];
}
if(par1 != par2) {
parents[par2] = par1;
--num;
}
}
island[val.first][val.second] = 1;
result.push_back(++num);
}
return result;
}
};
本文介绍了一种使用并查集(Union-Find)算法解决二维网格中岛屿计数问题的方法。通过给定的m x n网格及一系列操作,动态计算每次操作后岛屿的数量。挑战在于实现的时间复杂度为O(k log mn),其中k为操作次数。
933

被折叠的 条评论
为什么被折叠?



