《五月集训》第二十六天——并查集


前言

        并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。
刷题坚持每一天,以下题目引用自:力扣(LeetCode)

💎一、题目一

🏆1.题目描述

原题链接:990. 等式方程的可满足性

        给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:“a==b” 或 “a!=b”。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。
        只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false。

示例 1:
输入:[“a==b”,“b!=a”]
输出:false
解释:如果我们指定,a = 1 且 b = 1,那么可以满足第一个方程,但无法满足第二个方程。没有办法分配变量同时满足这两个方程。

🏆2.解题思路

🔑思路:

​         并查集,把相等的字符通过数组值把他们链接起来成一个集合。当查找不相等的时候,而它们却在一个集合里,返回false。否则返回true;

🏆3.代码详解

#define maxv 26
int pre[maxv];

void init(int size){
    for(int i = 0; i < size; ++i){
        pre[i] = i;
    }
}

int find (int x) {
    return pre[x] == x ? x : (pre[x]=find(pre[x]));
}

bool merge(int x, int y) {
    int rx = find(x), ry = find(y);
    if(rx == ry) return false;
    pre[ry] = rx;
    return true;
}

bool equationsPossible(char ** equations, int equationsSize){
    init(maxv);
    for(int i = 0; i < equationsSize; ++i){
        if(equations[i][1] == '='){
            merge(equations[i][0]-'a', equations[i][3]-'a');
        }
    }
    for(int i = 0; i < equationsSize; ++i){
        if(equations[i][1] == '!'){
            if(find(equations[i][0]-'a') == find(equations[i][3]-'a'))
                return false;
        }
    }
    return true;
}

💎二、题目二

🏆1.题目描述

原题链接:1319. 连通网络的操作次数

        用以太网线缆将 n 台计算机连接成一个网络,计算机的编号从 0 到 n-1。线缆用 connections 表示,其中 connections[i] = [a, b] 连接了计算机 a 和 b。
        网络中的任何一台计算机都可以通过网络直接或者间接访问同一个网络中其他任意一台计算机。
        给你这个计算机网络的初始布线 connections,你可以拔开任意两台直连计算机之间的线缆,并用它连接一对未直连的计算机。请你计算并返回使所有计算机都连通所需的最少操作次数。如果不可能,则返回 -1 。

示例 1:
Alt
输入:n = 4, connections = [[0,1],[0,2],[1,2]]
输出:1
解释:拔下计算机 1 和 2 之间的线缆,并将它插到计算机 1 和 3 上。

🏆2.解题思路

🔑思路:

​         合并连接的电脑,只要线缆够,通过hash记录集合的根,然后减去一个总根,返回剩余值就是最少步骤。

🏆3.代码详解

void init(int size, int* pre){
    for(int i = 0; i < size; ++i){
        pre[i] = i;
    }
}
//寻根
int find (int x, int* pre) {
    return pre[x] == x ? x : (pre[x]=find(pre[x], pre));
}
//合并
bool merge(int x, int y, int* pre) {
    int rx = find(x, pre), ry = find(y, pre);
    if(rx == ry) return false;
    pre[ry] = rx;
    return true;
}
int makeConnected(int n, int** connections, int connectionsSize, int* connectionsColSize){
    if(connectionsSize < n-1) return -1;
    int hash[n];
    int pre[n];
    int count = 0;
    init(n, pre);
    for(int i = 0; i < connectionsSize; ++i){
        merge(connections[i][0], connections[i][1], pre);
    }
    memset(hash, 0, sizeof(hash));
    for(int i = 0; i < n; ++i){
        int al = find(i, pre);
        if(!hash[al]){
            hash[al] = 1;
             ++count;
        }
    }
    return count-1;
}

💎三、星球推荐

        星球链接:英雄算法联盟

星球里有什么?
        【朋友圈】一个极致精准的自律、编程、算法的小圈子。
        【算法集训】以月为单位组织算法集训,每天四题,风雨无阻。
        【排行榜】每天、每周都会有榜单,激励大家不断进步,不断成长。
        【个人规划】每个人都写好自己的规划,也可以查看他人的规划,时刻警醒自己不掉队。
        【打卡挑战】每日一题打卡、每日早起打卡、算法集训打卡、规划完成情况打卡。
在星球里做什么?
        目前星球人数达到450+,在星球里你能够遇到一群志同道合之人,因为都是花钱进来的,你不会看到任何浑水摸鱼的人,每个人都有自己的每月规划,星主每月都会组织算法集训,每天一起刷题,你可以看到别人的解题报告,取其之长,补己之短。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值