Leetcode并查集:959. 由斜杠划分区域
题目链接:959. 由斜杠划分区域
方法一:将网格中每个坐标顶点作为并查集的节点
代码:
/**
* 方法一:把网格中每一个顶点作为并查集中的一个节点
* @param grid
* @return
*/
public int regionsBySlashes(String[] grid) {
int n = grid.length; // n*n的网格
int leftDown = 0; // 左下角坐标
int rightUp = 0; // 右上角坐标
int leftUp = 0; // 左上角坐标
int rightDown = 0; // 右下角坐标
UnionFind uf = new UnionFind(n);
for(int row = 0; row < grid.length; row++) {
for(int col = 0; col < grid.length; col++) { // 遍历grid数组,判断每一个字符
if(grid[row].charAt(col) == '/') {
leftDown = (row+1) * (n+1) + col;
rightUp = row * (n+1) + col + 1;
uf.merge(leftDown, rightUp); // 合并左下角和右上角节点
}else if(grid[row].charAt(col) == '\\') {
leftUp = row * (n+1) + col;
rightDown = (row+1) * (n+1) + col + 1;
uf.merge(leftUp, rightDown); // 合并左上角和右下角节点
}
}
}
return uf.getNumConnected();
}
class UnionFind{
private int[] father; // 存放每个节点的父节点
private int numConnected = 1; // 区域数
UnionFind(int n){
father = new int[(n+1)*(n+1)]; // 把网格中每一个顶点作为并查集中的一个节点
for(int row = 0; row < n+1; row++) {
for(int col = 0; col < n+1; col++) {
int vertexNum = row*(n+1)+col;
if(row == 0 || col == 0 || row == n || col == n) { // 将网格四周的顶点合并成一个连通分量
father[vertexNum] = 0;
}else {
father[vertexNum] = vertexNum;
}
}
}
}
public int find(int x) {
if(father[x] == x) {
return x;
}
int fatherX = find(father[x]);
father[x] = fatherX;
return fatherX;
}
public void merge(int a, int b) {
int fatherA = find(a);
int fatherB = find(b);
if(fatherA == fatherB) {
numConnected++; // 属于同一个连通分量,区域数+1
}else {
father[fatherA] = fatherB;
}
}
public int getNumConnected() {
return numConnected;
}
}
方法二:将每个网格划分为四个区域,每个区域作为并查集的节点
代码:
public int regionsBySlashes(String[] grid) {
int n = grid.length; // n*n的网格
int up = 0; // 一个网格中上边部分的标号
int right = 0; // 一个网格中右边部分的标号
int down = 0; // 一个网格中下边部分的标号
int left = 0; // 一个网格中左边部分的标号
int beforeDown = 0; // 上边网格的下部分标号
int beforeRight = 0 ; // 左边网格的右部分标号
UnionFind uf = new UnionFind(n);
for(int row = 0; row < grid.length; row++) {
for(int col = 0; col < grid.length; col++) { // 遍历grid数组,判断每一个字符
up = (row * n + col) * 4;
right = up + 1;
down = right + 1;
left = down + 1;
if(grid[row].charAt(col) == '/') {
uf.merge(up, left); // 合并上部分和左部分
uf.merge(right, down); // 合并右部分和下部分
}else if(grid[row].charAt(col) == '\\') {
uf.merge(up, right); // 合并上部分和右左部分
uf.merge(left, down); // 合并左右部分和下部分
}else {
uf.merge(up, right); // 合并所有四个部分
uf.merge(right, down);
uf.merge(down, left);
}
if(row > 0) {
beforeDown = ((row-1) * n + col) * 4 + 2;
uf.merge(up, beforeDown); // 合并上边网格的下部分
}
if(col > 0) {
beforeRight = (row * n + col - 1) * 4 + 1;
uf.merge(left, beforeRight); // 合并左边网格的右部分
}
}
}
return uf.getNumConnected();
}
class UnionFind{
private int[] father; // 存放每个节点的父节点
private int numConnected; // 区域数
UnionFind(int n){
father = new int[n*n*4]; // 将每个1/4区域作为一个节顶点
numConnected = n*n*4;
for(int i = 0; i < father.length; i++) {
father[i] = i; // 将每一个节点的父节点设置为自己
}
}
public int find(int x) { // 与方法一一致
if(father[x] == x) {
return x;
}
int fatherX = find(father[x]);
father[x] = fatherX;
return fatherX;
}
public void merge(int a, int b) {
int fatherA = find(a);
int fatherB = find(b);
if(fatherA != fatherB) { // 如果是同一个区域不用进行操作
father[fatherA] = fatherB;
numConnected--; // 将两个区域合并之后总的区域数就少了一个了
}
}
public int getNumConnected() {
return numConnected;
}
}
心得:
太久没有管博客,好多笔记都零零散散的躺着,得好好整理一下了!!!