并查集
核心思想:查询和合并
查询:查询根节点
合并:合并根节点
力扣(岛屿数量。200)
class Solution {
class UnionFind {
int count;
int[] parent;
int[] rank;
public UnionFind(char[][] grid) {
count = 0;
int m = grid.length;
int n = grid[0].length;
parent = new int[m * n];
rank = new int[m * n];
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == '1') {
parent[i * n + j] = i * n + j;
++count;
}
rank[i * n + j] = 0;
}
}
}
public int find(int i) {
if (parent[i] != i) parent[i] = find(parent[i]);
return parent[i];
}
public 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] += 1;
}
--count;
}
}
public int getCount() {
return count;
}
}
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
int nr = grid.length;
int nc = grid[0].length;
int num_islands = 0;
UnionFind uf = new UnionFind(grid);
for (int r = 0; r < nr; ++r) {
for (int c = 0; c < nc; ++c) {
if (grid[r][c] == '1') {
grid[r][c] = '0';
if (r - 1 >= 0 && grid[r-1][c] == '1') {
uf.union(r * nc + c, (r-1) * nc + c);
}
if (r + 1 < nr && grid[r+1][c] == '1') {
uf.union(r * nc + c, (r+1) * nc + c);
}
if (c - 1 >= 0 && grid[r][c-1] == '1') {
uf.union(r * nc + c, r * nc + c - 1);
}
if (c + 1 < nc && grid[r][c+1] == '1') {
uf.union(r * nc + c, r * nc + c + 1);
}
}
}
}
return uf.getCount();
}
}
力扣(省份数量547)
使用并查集。初始时,每个城市都属于不同的连通分量。遍历矩阵 如果两个城市之间有相连关系,则它们属于同一个,对它们进行合并。
class Solution {
public int findCircleNum(int[][] isConnected) {
int provinces = isConnected.length;
int[] parent = new int[provinces];
for (int i = 0; i < provinces; i++) {
parent[i] = i;
}
for (int i = 0; i < provinces; i++) {
for (int j = i + 1; j < provinces; j++) {
if (isConnected[i][j] == 1) {
union(parent, i, j);
}
}
}
int circles = 0;
for (int i = 0; i < provinces; i++) {
if (parent[i] == i) {
circles++;
}
}
return circles;
}
public void union(int[] parent, int index1, int index2) {
parent[find(parent, index1)] = find(parent, index2);
}
public int find(int[] parent, int index) {
if (parent[index] != index) {
parent[index] = find(parent, parent[index]);
}
return parent[index];
}
}
力扣(账户合并721)
class Solution {
public List<List<String>> accountsMerge(List<List<String>> accounts) {
Map<String, Integer> emailToIndex = new HashMap<String, Integer>();
Map<String, String> emailToName = new HashMap<String, String>();
int emailsCount = 0;
for (List<String> account : accounts) {
String name = account.get(0);
int size = account.size();
for (int i = 1; i < size; i++) {
String email = account.get(i);
if (!emailToIndex.containsKey(email)) {
emailToIndex.put(email, emailsCount++);
emailToName.put(email, name);
}
}
}
UnionFind uf = new UnionFind(emailsCount);
for (List<String> account : accounts) {
String firstEmail = account.get(1);
int firstIndex = emailToIndex.get(firstEmail);
int size = account.size();
for (int i = 2; i < size; i++) {
String nextEmail = account.get(i);
int nextIndex = emailToIndex.get(nextEmail);
uf.union(firstIndex, nextIndex);
}
}
Map<Integer, List<String>> indexToEmails = new HashMap<Integer, List<String>>();
for (String email : emailToIndex.keySet()) {
int index = uf.find(emailToIndex.get(email));
List<String> account = indexToEmails.getOrDefault(index, new ArrayList<String>());
account.add(email);
indexToEmails.put(index, account);
}
List<List<String>> merged = new ArrayList<List<String>>();
for (List<String> emails : indexToEmails.values()) {
Collections.sort(emails);
String name = emailToName.get(emails.get(0));
List<String> account = new ArrayList<String>();
account.add(name);
account.addAll(emails);
merged.add(account);
}
return merged;
}
}
class UnionFind {
int[] parent;
public UnionFind(int n) {
parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
public void union(int index1, int index2) {
parent[find(index2)] = find(index1);
}
public int find(int index) {
if (parent[index] != index) {
parent[index] = find(parent[index]);
}
return parent[index];
}
}