刷题笔记:并查集(续,LeetCode-959)

本文介绍了一种利用并查集解决LeetCode上“由斜杠划分区域”问题的方法。通过将每个单元格划分为四个三角形,并根据不同斜杠类型合并相应三角形来计算连通区域的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:由斜杠划分区域

原题链接:https://leetcode-cn.com/problems/regions-cut-by-slashes/

解析

题目需要求解连通块的个数,我们可以通过并查集进行求解,将联通的区域合并成同一个集合,最后求解集合的个数。
观察下图,我们把单元格分为4个三角形,并进行编号。
对单元格内的合并:

  • 如果是空格‘ ’,我们将(0,1,2,3)进行合并
  • 如果是斜杠‘/’,我们将(0,3),(1,2)进行合并
  • 如果是反斜杠‘\’,我们将(0,1),(2,3)进行合并
    在这里插入图片描述

对相邻单元格的合并,有4种方案:

  • 向右和向下
  • 向右和向上
  • 向左和向下
  • 向左和向上

在这里,我使用向右和向下合并。
在这里插入图片描述

代码

class UnionFind {
private:
    int count;
    vector<int> father;
public:
    int getCount(){
        return this->count;
    }
    UnionFind(int n){
        this->count=n;
        father.resize(n);
        for(int i=0;i<n;i++) father[i]=i;
    }
    int find_fa(int x){
        if(x==father[x]) return x;
        else {
            int f=this->find_fa(father[x]);
            father[x]=f;
            return f;
        }
    }
    void unino(int a,int b){
        int fa=this->find_fa(a);
        int fb=this->find_fa(b);
        if(fa!=fb) {
            father[fa]=fb;
            this->count--;
        }
    }
};
class Solution {
public:
    int regionsBySlashes(vector<string>& grid) {
        int len=grid.size();
        int N=4*len*len;
        UnionFind uf(N);
        for(int i=0;i<len;i++){
            int r=grid[i].size();
            for(int j=0;j<r;j++){
                int index=4*(i*len+j);
                //合并正方形内
                if(grid[i][j]=='/'){  //合并(0,3),(1,2)
                    uf.unino(index,index+3);
                    uf.unino(index+1,index+2);
                }else if(grid[i][j]=='\\'){   //合并(0,1),(2,3)
                    uf.unino(index,index+1);
                    uf.unino(index+2,index+3);
                }else{
                    uf.unino(index,index+1);
                    uf.unino(index+1,index+2);
                    uf.unino(index+2,index+3);
                }
                //合并区间外,向右,向下
                if(j+1<len){    //向右合并
                    uf.unino(index+1,4*(i*len+j+1)+3);
                }
                if(i+1<len){
                    uf.unino(index+2,4*((i+1)*len+j));
                }
            }
        }
        return uf.getCount();
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值