记录算法使用场景和算法实现
使用场景
将问题抽象为算法里的图,并查集算法可以根据结点之前关系连通和判断是否连通。
代码实现
c
typedef struct UnionFind {
// 记录连通分量的个数
int count;
int *parent;
int *size;
int (*find)(struct UnionFind *, int);
void (*munion)(struct UnionFind *, int, int);
bool (*isConnet)(struct UnionFind *, int, int);
} UnionFind;
void UFFree(UnionFind *obj) {
free(obj->parent);
free(obj->size);
free(obj);
return;
}
int UFFind(UnionFind *obj, int x) {
while (obj->parent[x] != x) {
// 路径压缩
obj->parent[x] = obj->parent[obj->parent[x]];
x = obj->parent[x];
}
return x;
}
void UFUnion(UnionFind *obj, int x, int y) {
int rootX = UFFind(obj, x);
int rootY = UFFind(obj, y);
if(rootX == rootY) return;
if(obj->size[rootX] > obj->size[rootY]) {
obj->parent[rootY] = rootX;
obj->size[rootX] += obj->size[rootY];
}
else {
obj->parent[rootX] = rootY;
obj->size[rootY] += obj->size[rootX];
}
obj->count--;
}
bool IsUFConnet(UnionFind *obj, int x, int y) {
return UFFind(obj, x) == UFFind(obj, y);
}
UnionFind *UFInit(int n) {
UnionFind *obj = (UnionFind *)malloc(sizeof(UnionFind));
obj->count = n;
obj->parent = (int *)malloc(sizeof(int)*n);
obj->size = (int *)malloc(sizeof(int)*n);
for(int i=0; i<n; i++) {
obj->parent[i] = i;
obj->size[i] = 1;
}
obj->find = UFFind;
obj->isConnet = IsUFConnet;
obj->munion = UFUnion;
return obj;
}
示例
题目浅析:矩形区域中填充'X'和'O',除矩形四边上为'O'及联通的'O'外,其余区域全变成'X'。
c
void solve(char** board, int boardSize, int* boardColSize) {
int m = boardSize;
int n = boardColSize[0];
UnionFind *obj = UFInit(m*n+1);
for(int i=0; i<m; i++) {
if(board[i][0] == 'O') {
obj->munion(obj, m*n, i*n);
}
if(board[i][n-1] == 'O') {
obj->munion(obj, m*n, i*n+n-1);
}
}
for(int j=0; j<n; j++) {
if(board[0][j] == 'O') {
obj->munion(obj, m*n, j);
}
if(board[m-1][j] == 'O') {
obj->munion(obj, m*n, (m-1)*n+j);
}
}
int dir[4][2] = {{0,-1}, {0,1}, {1,0}, {-1,0}};
for(int i=1; i<m-1; i++) {
for(int j=1; j<n-1; j++) {
if(board[i][j] == 'O') {
for(int k=0; k<4; k++) {
int ni = i+dir[k][0];
int nj = j+dir[k][1];
if(board[ni][nj] == 'O') {
obj->munion(obj, ni*n+nj, i*n+j);
}
}
}
}
}
for(int i=1; i<m-1; i++) {
for(int j=1; j<n-1; j++) {
if(!obj->isConnet(obj, m*n, i*n+j)) {
board[i][j] = 'X';
}
}
}
return;
}