LeetCode 305. 岛屿数量 II
题目描述
思路分析
解法一:并查集(推荐)
核心思路:
- 每次添加陆地时视作新岛屿,数量加一。
- 与四邻接陆地合并并减少岛屿数量。
- 使用并查集维护连通性。
复杂度分析:
- 时间复杂度:O(k * α(n)),其中 k 表示操作次数。
- 空间复杂度:O(m * n),用于并查集。
import java.util.ArrayList;
import java.util.List;
class Solution {
public List<Integer> numIslands2(int m, int n, int[][] positions) {
UnionFind uf = new UnionFind(m * n);
int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int count = 0;
List<Integer> res = new ArrayList<>();
for (int[] pos : positions) {
int r = pos[0];
int c = pos[1];
int id = r * n + c;
if (uf.active[id]) {
res.add(count);
continue;
}
uf.active[id] = true;
count++;
for (int[] d : dirs) {
int nr = r + d[0];
int nc = c + d[1];
if (nr < 0 || nr >= m || nc < 0 || nc >= n) {
continue;
}
int nid = nr * n + nc;
if (uf.active[nid] && uf.union(id, nid)) {
count--;
}
}
res.add(count);
}
return res;
}
static class UnionFind {
int[] parent;
int[] rank;
boolean[] active;
UnionFind(int n) {
parent = new int[n];
rank = new int[n];
active = new boolean[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
boolean union(int x, int y) {
int rx = find(x);
int ry = find(y);
if (rx == ry) {
return false;
}
if (rank[rx] < rank[ry]) {
parent[rx] = ry;
} else if (rank[rx] > rank[ry]) {
parent[ry] = rx;
} else {
parent[ry] = rx;
rank[rx]++;
}
return true;
}
}
}
func numIslands2(m int, n int, positions [][]int) []int {
uf := newUnionFind(m * n)
dirs := [][2]int{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}
count := 0
res := make([]int, 0, len(positions))
for _, pos := range positions {
r, c := pos[0], pos[1]
id := r*n + c
if uf.active[id] {
res = append(res, count)
continue
}
uf.active[id] = true
count++
for _, d := range dirs {
nr, nc := r+d[0], c+d[1]
if nr < 0 || nr >= m || nc < 0 || nc >= n {
continue
}
nid := nr*n + nc
if uf.active[nid] && uf.union(id, nid) {
count--
}
}
res = append(res, count)
}
return res
}
type unionFind struct {
parent []int
rank []int
active []bool
}
func newUnionFind(n int) *unionFind {
parent := make([]int, n)
rank := make([]int, n)
active := make([]bool, n)
for i := 0; i < n; i++ {
parent[i] = i
}
return &unionFind{parent: parent, rank: rank, active: active}
}
func (uf *unionFind) find(x int) int {
if uf.parent[x] != x {
uf.parent[x] = uf.find(uf.parent[x])
}
return uf.parent[x]
}
func (uf *unionFind) union(x int, y int) bool {
rx := uf.find(x)
ry := uf.find(y)
if rx == ry {
return false
}
if uf.rank[rx] < uf.rank[ry] {
uf.parent[rx] = ry
} else if uf.rank[rx] > uf.rank[ry] {
uf.parent[ry] = rx
} else {
uf.parent[ry] = rx
uf.rank[rx]++
}
return true
}
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 200. 岛屿数量 | 中等 | DFS/BFS |
| 547. 省份数量 | 中等 | 并查集 |
| 684. 冗余连接 | 中等 | 并查集 |
| 721. 账户合并 | 中等 | 并查集 |
| 803. 打砖块 | 困难 | 并查集 |
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议,转载请注明出处!