[leetcode] 并查集(Ⅱ)
最长连续序列
题目[128]:链接。
解题思路
节点本身的值作为节点的标号,两节点相邻,即允许合并(x, y)
的条件为x == y+1
。
因为数组中可能会出现值为 -1 的节点,因此不能把 root[x] == -1
作为根节点的特征,所以采取 root[x] == x
作为判断是否为根节点的条件。默认较小的节点作为连通分量的根。
此外,使用 map<int, int> counter
记录节点所在连通分量的节点个数(也是merge
的返回值)。
class Solution
{
public:
unordered_map<int, int> counter;
unordered_map<int, int> root;
int longestConsecutive(vector<int> &nums)
{
int len = nums.size();
// use map to discard the duplicate values
for (int x : nums)
root[x] = x, counter[x] = 1;
int result = len == 0 ? 0 : 1;
for (int x : nums)
{
if (root.count(x + 1) == 1)
result = max(result, merge(x, x + 1));
}
return result;
}
int find(int x)
{
return root[x] == x ? x : (root[x] = find(root[x]));
}
int merge(int x, int y)
{
x = find(x);
y = find(y);
if (x != y)
{
root[y] = x;
counter[x] += counter[y];
}
return counter[x];
}
};
连通网络的操作次数
题目[1319]:Link.
解题思路
考虑使用并查集。
考虑到特殊情况,要使 N 个点连通,至少需要 N-1 条边,否则返回 -1 即可。
通过并查集,可以计算出多余的边的数目(多余的边是指使得图成环的边),只要 findroot(x) == findroot(y)
说明边 (x,y)
使得图成环。
遍历所有边,在并查集中执行合并 merge
操作(多余的边忽略不合并,只进行计数)。设 components
为合并后后 root
数组中 -1 的个数(也就是连通分量的个数),要想所有的连通分支都连起来,需要 components - 1
个边,所以要求「多余的边」的数目必须大于等于 components - 1
。
一个简单的例子如下:
0--1 0--1 0--1
| / => | => | |
2 3 2 3 2 3
components = 2
duplicateEdge = 1
代码实现
class Solution
{
public:
vector<int> root;
int result = 0;
int makeConnected(int n, vector<vector<int>> &connections)
{
int E = connections.size();
// corner cases
if (n == 0 || n == 1)
return 0;
if (E < n - 1)
return -1;
root.resize(n), root.assign(n, -1);
// merge
for (auto &v : connections)
{
int a = v[0], b = v[1];
merge(a, b);
}
int components = count(root.begin(), root.end(), -1);
if (counter >= (components - 1))
return components - 1;
// should not be here
return -1;
}
int find(int x)
{
return root[x] == -1 ? x : (root[x] = find(root[x]));
}
// the number of duplicate edges
int counter = 0;
void merge(int x, int y)
{
x = find(x), y = find(y);
if (x != y)
root[y] = x;
else
{
// there is a duplicate edge
counter++;
}
}
};
等式方程的可满足性
题目[990]:Link.
解题思路
考虑并查集。遍历所有的包含 ==
的等式,显然,相等的 2 个变量就合并。对于不等式 x!=y
,必须满足 findroot(x) != findroot(y)
才不会出现逻辑上的错误。也就是说,不相等的 2 个变量必然在不同的连通分支当中。
#define getidx(x) ((x) - 'a')
class Solution
{
public:
vector<int> root;
bool equationsPossible(vector<string> &equations)
{
root.resize('z' - 'a' + 1, -1);
vector<int> notequal;
int len = equations.size();
for (int i = 0; i < len; i++)
{
auto &s = equations[i];
if (s[1] == '!')
{
notequal.emplace_back(i);
continue;
}
int a = getidx(s[0]), b = getidx(s[3]);
merge(a, b);
}
for (int i : notequal)
{
auto &s = equations[i];
int a = getidx(s[0]), b = getidx(s[3]);
if (find(a) == find(b))
return false;
}
return true;
}
int find(int x)
{
return (root[x] == -1) ? x : (root[x] = find(root[x]));
}
void merge(int x, int y)
{
x = find(x), y = find(y);
if (x != y)
root[y] = x;
}
};
尽量减少恶意软件的传播 II
题目[928]:
预备知识 并查集 (Union Set) 一种常见的应用是计算一个图中连通分量的个数.比如: a e / \ | b c f | | d g 上图的连通分量的个数为 2 . 并查集的主要思想是在每个连 ... 婴儿名字 题目[Interview-1707]:典型并查集题目. 解题思路 首先对 names 这种傻 X 字符串结构进行预处理,转换为一个 map,key 是名字,val 是名字出现的次数. 然后是 ... Leetcode之并查集专题-765. 情侣牵手(Couples Holding Hands) N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并 ... Leetcode之并查集专题-684. 冗余连接(Redundant Connection) 在本问题中, 树指的是一个连通且无环的无向图. 输入一个图,该图由一个有着N个节点 (节点值不重复1, 2 ... 链接:https://leetcode.com/tag/union-find/ [128]Longest Consecutive Sequence (2018年11月22日,开始解决hard题) 给 ... 题目描述: 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 ... 800. Similar RGB Color class Solution { int getn(int k){ return (k+8)/17; } string strd(int k){ char ... 721. 账户合并 给定一个列表 accounts,每个元素 accounts[i] 是一个字符串列表,其中第一个元素 accounts[i][0] 是 名称 (name),其余元素是 emails ... 并查集篇 # 题名 刷题 通过率 难度 128 最长连续序列 39.3% 困难 130 被围绕的区域 30.5% 中等 200 岛屿的个数 38.4% 中等 547 朋友圈 45.1% ... # 目前公司用的是阿里云的容器服务 所以本地搭建个单机版 方便测试使用# VMware® Workstation 12 Pro 版本# 虚拟机环境配置:配置 2核 4G 网络桥接# 系统镜像: Cen ... 不多扯题目 直接题解= = 1.递归 由题目可以得知,子树既可以是根节点和叶节点组成,也可以是一个节点,题意中的对称二叉子树是必须由一个根节点一直到树的最底部所组成的树. 这样一来就简单了,我们很容易 ... ubuntu16 安装redis并开机自启 1.redis-3.2.5.tar.gz解压到/usr/local下 tar -xvf redis-3.2.5.tar.gz 2.进入源码包/usr/loc ... C. Coffee Break 这个贪心之前好像写过,还是感觉挺难的,有点不会写. 这个题目大意是:给你一个数列n个元素,然后给你一天的时间,给你一个间隔时间d, 问你最少要用多少天可以把这个数列的所 ... 上篇文章我们学习了官网中的1.2,1.3两小节,主要是涉及了容器,以及Spring实例化对象的一些知识.这篇文章我们继续学习Spring官网,主要是针对1.4小节,主要涉及到Spring的依赖注入.虽 ... 组合接口时的名字冲突: 看下面这段代码: interface I1 { int f(); } interface I2 { void f(); } interface I3 { int f(int a ... 文章目录 1 前言 2 自然坐标系ABC 3 αβ\alpha\betaαβ 坐标系 3.1 Clarke变换 3.2 Clarke反变换 4 dqdqdq 坐标系 4.1 Park变换 正转 反转 ... 文章目录 1 下载文件创建rootfs文件夹 2 安装qemu-user-static搭建arm64模拟环境 3 chroot 到 模拟arm64的文件系统下 4 安装基础的软件包 5 系统基础的修改 ... 多线程实践 前面的一些文章和脚本都是只能做学习多线程的原理使用,实际上什么有用的事情也没有做.接下来进行多线程的实践,看一看在实际项目中是怎么使用多线程的. 图书排名示例 Bookrank.py: 该 ... 首先,让我们看看两个特别的字符:'^' 和 ‘$' 他们是分别用来匹配字符串的开始和结束,一下分别举例说明"^The": 匹配以 "The"开头的字符串;&qu ...[leetcode] 并查集(Ⅱ)的更多相关文章
随机推荐