[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% ... 在linux上部署自己开发的web项目 前言:相信有很多做开发的小伙伴和我之前一样,只会在windows环境下,利用开发工具开发运行web项目,但是却不知道怎么把开发好的项目部署到linux服务器上去 ... E. Array Shrinking 题目大意: 给你一个大小是n的序列,相邻的序列如果相等,则可以合并,合并之后的值等于原来的值加1. 求:合并之后最小的序列的和. 题解: 这个数据范围和这个相邻的 ... 求一个 a*x*x*x+b*x*x+c*x+d 的解 题目很简单,但是我输出了-0.00,然后就一直卡着,这个问题以后要注意. 让0.00 编程-0.00的方法有很多. 第一种就是直接特判 if(fa ... 一.多对一的映射关系 举例:根据员工编号查询员工所在部门的部门信息 第一步,需要在多的一方也就是员工实体类中持有一的一方部门实体类的引用 第二步,在dao接口中声明方法 第三步,在mapper中实现该 ... Scrapy+selenium爬取简书全站 环境 Ubuntu 18.04 Python 3.8 Scrapy 2.1 爬取内容 文字标题 作者 作者头像 发布日期 内容 文章连接 文章ID 思路 分 ... 类中属性的隐式初始化,代码如下,我们看下不同类型默认的初始值是什么 创建一个Demo类如下: class Demo { int a; byte b; short c; long d; boolean ... 有的员工,没有公司开户行的银行卡,发放现金工资.有时人多,需要计算币数.现金工资表中,其中一列为实发工资,import pandas as pd,转化为pd.DataFrame. 面值[100,50, ... 消费者如何读取数据? 前一篇是生产者的处理,这一篇讲消费者的处理 我们都知道,消费者无非就是不停地从队列中读取数据,处理数据.但是与BlockedQueue不同的是,RingBuffer的消费者不会对 ... 原错误提示:App is not indexable by Google Search; consider adding at least one Activity with an ACTION-VI ... 列表:python中不用定义类型,类似工厂 列表的创建: ①创建普通列表:[1,2],用逗号隔开 ②创建一个混合列表:[1,‘zyf',3.14,[1,2,3]] ③创建空列表:empty=[] 常用 ...[leetcode] 并查集(Ⅱ)的更多相关文章
随机推荐