岛屿数量 II
难度:
标签:
题目描述
代码结果
运行时间: 100 ms, 内存: 20.4 MB
/*
题目思路:
1. 使用Java Stream API来简化代码结构,但核心逻辑依然是使用并查集进行处理。
2. 使用数组记录每个位置的父节点,以此构建并查集。
3. 每次添加新的陆地时,利用Stream对周围的陆地进行合并操作。
4. 返回每次添加操作后的岛屿数量。
*/
import java.util.*;
import java.util.stream.IntStream;
public class NumberOfIslandsIIStream {
private int[] parent;
private int[] rank;
private int count;
public List<Integer> numIslands2(int m, int n, int[][] positions) {
List<Integer> result = new ArrayList<>();
parent = new int[m * n];
rank = new int[m * n];
Arrays.fill(parent, -1);
count = 0;
int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
for (int[] position : positions) {
int row = position[0];
int col = position[1];
int index = row * n + col;
if (parent[index] != -1) { // already land
result.add(count);
continue;
}
parent[index] = index;
count++;
IntStream.range(0, directions.length)
.mapToObj(i -> new int[]{row + directions[i][0], col + directions[i][1], (row + directions[i][0]) * n + (col + directions[i][1])})
.filter(newPos -> newPos[0] >= 0 && newPos[0] < m && newPos[1] >= 0 && newPos[1] < n && parent[newPos[2]] != -1)
.forEach(newPos -> union(index, newPos[2]));
result.add(count);
}
return result;
}
private int find(int i) {
if (parent[i] != i) {
parent[i] = find(parent[i]); // path compression
}
return parent[i];
}
private void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else {
parent[rootY] = rootX;
rank[rootX]++;
}
count--;
}
}
}
解释
方法:
此题解采用了并查集的数据结构来追踪和管理岛屿的连接状态。每个单元格都初始化为其自身的代表(自环),表示各自为独立的岛屿。遍历每个位置,若当前位置是陆地,则检查其四周的单元格。如果相邻的单元格已经是陆地,并且属于不同的集合,则通过合并这两个集合来减少岛屿数量。每合并一次,岛屿数量减一。最后,将当前的岛屿数量加入结果列表。
时间复杂度:
O(m)
空间复杂度:
O(row * col + m)
代码细节讲解
🦆
在并查集中,每次合并两个岛屿时,为什么选择将一个岛屿的代表节点直接指向另一个岛屿的代表节点?这样的操作是否会影响结构的平衡性?
▷🦆
在处理边界条件时,你是如何确保不会对数组越界进行操作的?具体是通过哪些条件来判断的?
▷🦆
并查集数据结构在初始化时将每个点设为自己的代表。这种初始化方式是否适用于所有并查集的应用场景,还是仅限于特定问题?
▷🦆
在遍历positions并更新岛屿数量时,如果同一个位置多次出现在positions中,当前的实现会如何处理?这是否会影响最终的岛屿数量统计?
▷相关问题
岛屿数量
给你一个由 '1'
(陆地)和 '0'
(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [ ["1","1","1","1","0"], ["1","1","0","1","0"], ["1","1","0","0","0"], ["0","0","0","0","0"] ] 输出:1
示例 2:
输入:grid = [ ["1","1","0","0","0"], ["1","1","0","0","0"], ["0","0","1","0","0"], ["0","0","0","1","1"] ] 输出:3
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j]
的值为'0'
或'1'