Para el problema de la isla anterior, es más fácil y eficiente usar DFS y BFS que usar la búsqueda de unión, pero para esta pregunta, 827. La isla artificial más grande , es más fácil usar la búsqueda de unión.
[Título] Se le da una n x n
matriz binaria de tamaño grid
. Solo una cuadrícula de 0 se puede cambiar a 1 como máximo. Después de hacer esto, grid
¿cuál es el área insular más grande de ? 岛屿
Está formado por un grupo de 1 conectados en cuatro direcciones: arriba, abajo, izquierda y derecha.
El requisito de la pregunta es cambiar una cuadrícula de 0 a 1 y luego ver cuánto puede medir la isla más grande. Por lo tanto, puede usar arriba, abajo, izquierda y derecha para juzgar el tamaño de la isla y el 0 actual. combinación para registrar la isla más grande. La idea es la siguiente:
- El primer recorrido
grid
: registre todas las islas yrank
obtenga el área de las islas a través; - El segundo recorrido
grid
: cuando encuentre una posición de 0, registre el área de las islas conectadas por el área de las islas superior, inferior, izquierda y derecha después de cambiar la posición actual a 1. El método específico:- Use una variable
area = 1
para registrar el área; - Determine si las posiciones superior, inferior, izquierda y derecha son 1, y si es 1, obtenga el área de la isla y súmela a
area
; - También recuerde agregar una variable adicional
seen
para registrar si se ha visto la isla. Porque es posible que haya islas arriba, abajo, izquierda y derecha que pertenezcan a la misma isla;
- Use una variable
Primero implemente el conjunto de búsqueda de unión:
class UnionFind {
public:
int count;
vector<int> parent;
vector<int> rank;
UnionFind(int n) {
count = n;
parent = vector<int>(n);
rank = vector<int>(n, 1);
for (int i = 0; i < parent.size(); i++) {
parent[i] = i;
}
}
int Find(int x) {
if (parent[x] != x) {
parent[x] = Find(parent[x]);
}
return parent[x];
}
void Union(int x, int y) {
int root_x = Find(x), root_y = Find(y);
if (root_x == root_y) {
return; }
if (rank[root_x] >= rank[root_y]) {
parent[root_y] = root_x;
rank[root_x] += rank[root_y];
} else {
parent[root_x] = root_y;
rank[root_y] += rank[root_x];
}
}
};
Entonces la lógica principal del tema:
class Solution {
public:
int largestIsland(vector<vector<int>>& grid) {
// 遍历整个 grid 创建并查集
int n = grid.size();
UnionFind uf(n * n);
int dx[4] = {
-1, 1, 0, 0};
int dy[4] = {
0, 0, -1, 1};
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
for (int k = 0; k < 4; k++) {
int nx = i + dx[k];
int ny = j + dy[k];
if (nx >= 0 && nx < n && ny >= 0 && ny < n && grid[nx][ny] == 1) {
uf.Union(i * n + j, nx * n + ny);
}
}
}
}
}
int maxArea = 0;
// 遍历所有的 0, 并且判断如果将这个 0 变为 1 之后的最大面积是多少
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
// 直接比较当前的面积大小
maxArea = max(maxArea, uf.rank[uf.Find(i * n + j)]);
} else if (grid[i][j] == 0) {
int area = 1; // 当前位置变为 1
set<int> seen;
for (int k = 0; k < 4; k++) {
int nx = i + dx[k];
int ny = j + dy[k];
if (nx >= 0 && nx < n && ny >= 0 && ny < n && grid[nx][ny] == 1) {
int root_x = uf.Find(nx * n + ny);
if (seen.count(root_x) == 0) {
area += uf.rank[root_x];
seen.insert(root_x);
}
}
}
maxArea = max(maxArea, area);
}
}
}
return maxArea;
}
};
La solución al problema de LeetCode es: ¡ Finalmente se pone en juego el poder de la búsqueda de sindicatos! [C++ y conjunto de verificación]