并查集详解参考https://blog.csdn.net/moX980/article/details/107782408
Leetcode130
题目分析:注意解释里的文字!!!将被X包围的O都连通在一起,而在边界上O都与某个特定的点连通(比如0),连通操作结束后,遍历一遍表,将没有与0连通的O改为X即可
注意并查集的表示方法是一个数组,将2*2的board转化为一维的,将0位空出用作连同边界上的O
遍历board:
- 当board[i] [j] 为X时,跳过
- 不为X就为O 当O在边界处,i == 0 || i == n-1 || j == 0 || j == m - 1,将这个位置与0连通
- 当O不在边界处,检查此点的上左是否为O,为O连通(虽然不在边界处,但可能通过连通连接到边界的O)
class Solution {
public:
class UnionSet{
public:
int *fa, *cnt;
UnionSet(int n){
fa = new int[n + 1];
cnt = new int[n + 1];
for(int i = 0; i <= n; i++){
fa[i] = i;
cnt[i] = 1;
}
}
int find(int x){
//路径压缩
return fa[x] = (x == fa[x] ? x : find(fa[x]));
}
void merge(int a, int b){
int aa = find(a), bb = find(b);
if(aa == bb) return ;
//按weighted优化
if(cnt[aa] > cnt[bb]) swap(aa, bb);
fa[bb] = aa;
cnt[aa] += cnt[bb];
return ;
}
~UnionSet(){
delete[] fa;
delete[] cnt;
}
};
int n, m;
int ind(int i, int j){
return i * m + j + 1;
}
void solve(vector<vector<char>>& board) {
if(board.size() == 0) return ;
n = board.size();
m = board[0].size();
UnionSet u(n * m);
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(board[i][j] == 'X') continue;
if(i && board[i - 1][j] == 'O') u.merge(ind(i, j), ind(i - 1, j));
if(j && board[i][j - 1] == 'O') u.merge(ind(i, j), ind(i, j - 1));
if(i == 0 || i == n - 1) u.merge(0, ind(i, j));
if(j == 0 || j == m - 1) u.merge(0, ind(i, j));
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(board[i][j] == 'X') continue;
if(u.find(ind(i, j)) == u.find(0)) continue;
board[i][j] = 'X';
}
}
return ;
}
};
Leetcode547
题目分析:并查集,遍历所给的表,如果ij为1,就连同i和j,连通操作结束后,遍历并查集,只要是fa[i] == i(自己是自己的父节点),说明自己是一个子树的根节点,有多少根节点就有多少朋友圈
class Solution {
public:
class UnionSet{
public:
int *fa, *cnt;
UnionSet(int n){
fa = new int[n];
cnt = new int[n];
for(int i = 0; i < n; i++){
fa[i] = i;
cnt[i] = 1;
}
}
int find(int x){
return fa[x] = (x == fa[x] ? x : find(fa[x]));
}
void merge(int a, int b){
int aa = find(a), bb = find(b);
if(aa == bb) return ;
if(cnt[aa] > cnt[bb]) swap(aa, bb);
fa[aa] = bb;
cnt[bb] += cnt[aa];
return ;
}
~UnionSet(){
delete[] fa;
delete[] cnt;
}
};
int findCircleNum(vector<vector<int>>& M) {
if(M.size() == 0) return 0;
int n = M.size();
UnionSet u(n);
for(int i = 0; i < n; i++){
for(int j = i + 1; j < n; j++){
if(M[i][j] == 0) continue;
u.merge(i, j);
}
}
int ans = 0;
for(int i = 0; i < n; i++){
if(u.find(i) == i) ans++;
}
return ans;
}
};