并查集-下
题目1
题目链接:947. 移除最多的同行或同列石头
解题思路
- 维护两个哈希表,用来记录某行或某列遇到的第一块石头,key记录某行,value记录石头编号
- 遍历石头数组,如果这块石头不在行哈希表中,将其放入行哈希表,如果在,将其与行哈希表中的石头合并,列同理
- 遍历完后,移除的石头数量等于原先石头数减去现在集合数
代码
1 | class Solution { |
题目2
解题思路
- 维护一个
secret数组,用来记录以某个节点为代表元素的集合是否知道秘密,初始化时只有0和firstPerson知道秘密 - 将会议数组按会议开始时间从小到大排序,找出在同一时刻开始的会议
- 将所有专家进行
union,最终知道秘密的专家和不知道秘密的专家会被放入两个集合 - 将不知道秘密的专家集合拆散
- 到第二个时刻重复上述操作
- 最终遍历所有专家,若其所在连通分量的根知道秘密,则加入答案。
代码
1 | class Solution { |
题目3
题目链接:2421. 好路径的数目
解题思路
- 初始化
- 每个节点独立成一个集合;
maxcnt[i] = 1:表示以i为根的集合中,最大值(即vals[i])出现的次数为 1;- **初始答案 **
ans = n(每个节点自身是一条好路径)。
- 对边排序
- **按 **
max(vals[u], vals[v])升序排序。 - 这确保我们在处理某条边时,其两端的节点值都不超过当前“激活阈值”。
- **按 **
- 依次处理每条边
- **找到两个端点所在集合的根 **
fx,fy; - **比较 **
val[fx]和vals[fy]- 若不等:将较小值的集合合并到较大值的集合(保留更大值作为新根);
- **若相等:说明两个集合的最大值相同,此时新增好路径数 = **
maxcnt[fx] * maxcnt[fy],然后合并,并更新maxcnt。
- **找到两个端点所在集合的根 **
- 返回总路径数。
代码
1 | class Solution { |
题目4
解题思路
- 第一步:预处理
- **标记所有 **
initial节点为“病毒节点”。 - **初始化并查集,**只用于普通节点(病毒节点不参与合并)。
- 第二步:合并普通节点
- **遍历所有边,**仅当两个端点都是普通节点时才合并。
- 得到若干个纯净的普通连通分量,每个分量有:
- 代表元(根)
- 大小(
size[root])
- 第三步:标记每个分量的感染源
-
**对每个病毒节点 **
1
sick ∈ initial
-
**遍历其所有邻居 **
neighbour; -
**若 **
neighbour是普通节点且与sick相连: -
**找到 **
neighbour所在分量的根root; -
标记该分量的感染源:
- **若首次被感染 → 记录 **
infect[root] = sick; - **若已有一个不同感染源 → 标记为 **
infect[root] = -2(多源,无法拯救)。
- **若首次被感染 → 记录 **
-
**4.**第四步:统计拯救收益
- 对每个普通连通分量(仅看代表元):
- **若 **
infect[root] >= 0(唯一感染源), - **则 **
cnts[infect[root]] += size[root]。
- **若 **
**5.**第五步:选择最优删除节点
- **在 **
initial中,选择cnts[x]最大的x; - **若相同,选编号最小的(先排序 **
initial即可保证)。
代码
1 | class Solution { |
本文是原创文章,采用CC BY-NC-SA 4.0协议,完整转载请注明来自Heaven
