一、算法-并查集
// Find
HashMap<Integer, Intger> father = new HashMap<>();
pubic int find(int x) {
int parent = father.get(x);
while (parent != father.get(parent)) {
parent = father.get(parent);
}
return parent;
}
//Time Complexity O(n)
// Union
// union(E, B)
HashMap<Integer, Integer> father = new HashMap<>();
public void union(int x, int y) {
int fa_x = find(x);
int fa_y = find(y);
if (fa_x != fa_y) {
father.put(fa_x, fa_y);
}
}
// Time Complexity O(n)
//并查集优化
// Time Complexity O(1)
class UnionFind {
HashMap<Integer, Integer> father = new HashMap<>();
//初始化
UnionFind(int n) {
for (int i = 0; i < n; i++) {
father.put(i, i);
}
}
//Time Complexity O(1)
int find2(int x) {
//find2 搜索真正的父节点parent
int parent = father.get(x);
while (parent != father.get(parent)) {
parent = father.get(parent);
}
//临时变量
int temp = -1;
int fa = father.get(x);
while (fa != father.get(fa)) {
temp = father.get(fa);
//parent真正的父节点,直接替换,O(1)实现的基础
father.put(fa, parent);
fa = temp;
}
return parent;
}
void union(int x, int y) {
int fa_x = find2(x);
int fa_y = find2(y);
if (fa_x != fa_y) {
father.put(fa_x, fa_y);
}
}
}
二、小岛问题2
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
class Point {
int x;
int y;
Point() {
x = 0;
y = 0;
}
Point(int a, int b) {
x = a;
y = b;
}
}
public class NumberOfIsland2 {
public static void main(String[] args) {
int n = 4;
int m = 5;
Point[] operators = new Point[4];
Point point1 = new Point(1, 1);
Point point2 = new Point(0, 1);
Point point3 = new Point(3, 3);
Point point4 = new Point(3, 4);
operators[0] = point1;
operators[1] = point2;
operators[2] = point3;
operators[3] = point4;
List<Integer> list = new NumberOfIsland2().numIslands(n, m, operators);
for (int number: list) {
System.out.println(number);
}
}
//O(1)的并查集
class UnionFind {
private Map<Integer, Integer> father = new HashMap<>();
public UnionFind(int row, int column) {
for (int i = 0; i < row; i ++) {
for (int j = 0; j < column; j++) {
int id = convertedId(i, j, column);
father.put(id, id);
}
}
}
public int find(int x) {
int parent = father.get(x);
while (parent != father.get(parent)) {
parent = father.get(parent);
}
int temp = -1;
int fa = father.get(x);
while (fa != father.get(fa)) {
temp = father.get(fa);
father.put(fa, parent);
fa = temp;
}
return parent;
}
public void union(int x, int y) {
int parent_x = father.get(x);
int parent_y = father.get(y);
if (parent_x != parent_y) {
father.put(parent_x, parent_y);
}
}
//二维转成一维
public int convertedId(int x, int y, int row) {
return x * row + y;
}
}
//小岛问题求解,使用之前的bfs宽度优先搜索也可以实现
public List<Integer> numIslands(int n, int m, Point[] operators) {
List<Integer> result = new ArrayList<>();
if (operators == null || operators.length == 0) {
return result;
}
UnionFind unionFind = new UnionFind(n, m);
boolean[][] island = new boolean[n][m];
//上下左右节点
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
int count = 0;
for (Point point: operators) {
int x = point.x;
int y = point.y;
if (!island[x][y]) {
island[x][y] = true;
count++;
int id = unionFind.convertedId(x, y, m);
for (int i = 0; i < 4; i++) {
int current_x = x + dx[i];
int current_y = y + dy[i];
if (current_x >= 0 && current_x < n
&& current_y >= 0 && current_y < m
&& island[current_x][current_y]) {
int nid = unionFind.convertedId(current_x, current_y, m);
int father = unionFind.find(id);
int nfather = unionFind.find(nid);
//上下左右节点,不是共同的father则unionFind.union合并,小岛数量-1
if (father != nfather) {
count--;
unionFind.union(father, nfather);
}
}
}
result.add(count);
}
}
return result;
}
}