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;
}
};