链接:https://leetcode.com/tag/union-find/

【128】Longest Consecutive Sequence  (2018年11月22日,开始解决hard题)

给了一个无序的数组,问这个数组里面的元素(可以重新排序)能组成的最长的连续子序列是多长。本题的时间复杂度要求是 O(N).

本题 array 专题里面有, 链接:https://www.cnblogs.com/zhangwanying/p/9610923.html ,用个 hashmap 可以做到 O(N).

本题用 union-find 怎么解,不知道 orz。

【130】Surrounded Regions (2019年1月31日,UF专题)

给了个二维 grid,把里面 O 全部变成 X,但是 边界和边界联通区域内的 O 保留。

题解:我以前是用dfs解的。今天看了discuss高票使用UF,学习了一下。我们把边界上的 O 和边界联通区域内的 O 的坐标与一个 dummy node 联通就好了。然后遍历 grid,如果坐标与 dummy node 坐标联通,就保留成 O,不然改成 X

 class UF {
public:
UF(int size) {
father.resize(size);
rank.resize(size, );
for (int i = ; i < size; ++i) {
father[i] = i;
}
}
int find(int x) {
return x == father[x] ? x : father[x] = find(father[x]);
}
void connect(int x, int y) {
int xx = find(x), yy = find(y);
if (xx == yy) { return; }
if (yy > xx) {
father[xx] = yy;
} else {
father[yy] = x;
}
}
vector<int> father;
vector<int> rank;
};
class Solution {
public:
void solve(vector<vector<char>>& board) {
if (board.empty() || board[].empty()) { return; }
const int n = board.size(), m = board[].size();
UF uf(n * m + );
for (int i = ; i < n; ++i) {
for (int j = ; j < m; ++j) {
if (board[i][j] == 'O') {
if ((i == || i == n- || j == || j == m-)) {
uf.connect(i * m + j, n * m);
} else {
if (board[i-][j] == 'O') {
uf.connect(i * m + j, (i-) * m + j);
}
if (board[i+][j] == 'O') {
uf.connect(i * m + j, (i+) * m + j);
}
if (board[i][j-] == 'O') {
uf.connect(i * m + j, i * m + j - );
}
if (board[i][j+] == 'O') {
uf.connect(i * m + j, i * m + j + );
}
}
}
}
}
for (int i = ; i < n; ++i) {
for (int j = ; j < m; ++j) {
if (uf.find(i * m +j) != n * m) {
board[i][j] = 'X';
}
}
}
return;
}
};

【200】Number of Islands  (2019年1月31日,UF专题)

给了一个二维的grid,0 代表海, 1 的联通块代表岛屿,问有多少岛屿。

题解:和130题一样的想法。判断当前结点和上下左右四个结点是不是都是1,如果是的话,就联通这两个点。

 class UF {
public:
UF(int size) {
father.resize(size);
rank.resize(size, );
for (int i = ; i < size; ++i) {
father[i] = i;
}
}
int find(int x) {
return x == father[x] ? x : father[x] = find(father[x]);
}
void connect(int x, int y) {
int xx = find(x), yy = find(y);
if (xx == yy) { return; }
if (yy < xx) {
father[xx] = yy;
} else {
father[yy] = xx;
}
}
vector<int> father;
vector<int> rank;
};
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
if (grid.size() == || grid[].size() == ) {
return ;
}
const int n = grid.size(), m = grid[].size();
UF uf(n * m);
for (int i = ; i < n; ++i) {
for (int j = ; j < m; ++j) {
int index = i * m + j;
if (grid[i][j] == '') {
if (i - >= && grid[i-][j] == '') {
uf.connect(index, (i-) * m + j);
}
if (i + < n && grid[i+][j] == '') {
uf.connect(index, (i+) * m + j);
}
if (j - >= && grid[i][j-] == '') {
uf.connect(index, i * m + j - );
}
if (j + < m && grid[i][j+] == '') {
uf.connect(index, i * m + j + );
}
}
}
}
int ret = ;
for (int i = ; i < n; ++i) {
for (int j = ; j < m; ++j) {
int index = i * m + j;
if (grid[i][j] == '' && uf.find(index) == index) {
ret++;
}
}
}
return ret;
}
};

【261】Graph Valid Tree (2019年1月31日,UF专题)

给了 N 个结点 和 一个边的集合,问这个边的集合能不能构成一棵树。

题解:先检查 边集合大小是否等于 N-1, 然后用并查集检查是否有环,没有的话,就是树。

 class UF {
public:
UF(int size) {
father.resize(size);
for (int i = ; i < size; ++i) {
father[i] = i;
}
}
int find (int x) {
return x == father[x] ? x : father[x] = find(father[x]);
}
void connect (int x, int y) {
int xx = find(x), yy = find(y);
if (xx == yy) { return; }
if (xx < yy) {
father[yy] = xx;
} else {
father[xx] = yy;
}
}
vector<int> father;
};
class Solution {
public:
bool validTree(int n, vector<pair<int, int>>& edges) {
const int edgeSize = edges.size();
if (edgeSize != n-) { return false; } // n 个结点的树有 n-1 条边
UF uf(n);
for (auto& e: edges) {
int u = uf.find(e.first), v = uf.find(e.second);
if (u == v) {
return false;
}
uf.connect(e.first, e.second);
}
return true;
}
};

【305】Number of Islands II (2019年1月31日,UF专题)

【323】Number of Connected Components in an Undirected Graph (2019年2月2日,UF tag专题)

给了 n 个结点,编号从 0 到 n-1,以及一个边的集合。问这个无向图里面有多少个联通块。

题解:直接 uf 数联通块。

 class UF {
public:
UF(int size) {
father.resize(size);
for (int i = ; i < size; ++i) {
father[i] = i;
}
}
int find(int x) {
return x == father[x] ? x : father[x] = find(father[x]);
}
void connect(int x, int y) {
int xx = find(x), yy = find(y);
if (xx == yy) { return; }
if (yy < xx) {
father[xx] = yy;
} else {
father[yy] = xx;
}
}
int getCount() {
int count = ;
for (int i = ; i < father.size(); ++i) {
if (father[i] == i) {
count++;
}
}
return count;
}
vector<int> father;
};
class Solution {
public:
int countComponents(int n, vector<pair<int, int>>& edges) {
UF uf(n);
for (auto& e : edges) {
int u = e.first, v = e.second;
uf.connect(u, v);
}
return uf.getCount();
}
};

【547】Friend Circles (2019年2月2日,UF tag专题)

给了一个邻接矩阵, M[i][j]  = 1代表 i,j 是朋友关系,我们算上间接朋友关系,问这个矩阵里面一共有几个朋友圈子?

题解:直接用 uf 数这个图里面有多少联通块。

 class UF {
public:
UF(int size) {
father.resize(size);
for (int i = ; i < size; ++i) {
father[i] = i;
}
}
int find(int x) {
return x == father[x] ? x : father[x] = find(father[x]);
}
void connect(int x, int y) {
int xx = find(x), yy = find(y);
if (xx == yy) { return; }
if (yy < xx) {
father[xx] = yy;
} else {
father[yy] = xx;
}
}
vector<int> father;
};
class Solution {
public:
int findCircleNum(vector<vector<int>>& M) {
const int n = M.size();
UF uf(n);
for (int i = ; i < n; ++i) {
for (int j = ; j < n; ++j) {
if (M[i][j] == ) {
uf.connect(i, j);
}
}
}
int ret = ;
for (int i = ; i < uf.father.size(); ++i) {
if (i == uf.father[i]) {
ret++;
}
}
return ret;
}
};

【684】Redundant Connection (2018年11月22日,contest 51 模拟赛做到了)

在本题中,树是一个无环的无向图。输入一个N个结点(编号是1~N)的图,有一条边是多余的,把这条边找出来。

Example :
Input: [[,], [,], [,]]
Output: [,]
Explanation: The given undirected graph will be like this:
/ \
- Example :
Input: [[,], [,], [,], [,], [,]]
Output: [,]
Explanation: The given undirected graph will be like this:
- -
| |
- Note:
The size of the input 2D-array will be between and .
Every integer represented in the 2D-array will be between and N, where N is the size of the input array.

题解:我是用并查集解的。对于每一条边的两个结点,如果他们的爸爸不是同一个爸爸,那么就 unoin 这两个结点,如果他们两个的爸爸是同一个爸爸,就说明这条边多余了,直接返回这条边就行了。

 class Solution {
public:
int findfather(int x) {
return x == father[x] ? x : findfather(father[x]);
}
void unionNode(int x, int y) {
x = findfather(x);
y = findfather(y);
if (x == y) { return; }
father[y] = x;
} vector<int> findRedundantConnection(vector<vector<int>>& edges) {
n = edges.size();
father.resize(n+); //redundant 0
for (int i = ; i < n+; ++i) {
father[i] = i;
}
vector<int> ret;
for (auto e : edges) {
int u = min(e[], e[]), v = max(e[], e[]);
if (findfather(v) == findfather(u)) {
ret = e;
break;
} else {
unionNode(u, v);
}
}
return ret;
}
int n = ;
vector<int> father; };

【685】Redundant Connection II (2019年2月2日,UF专题)(Hard)

给了 1~N,N个结点,N条边的有向图,删除一条边之后能形成一棵树,返回需要删除的那条边,如果有多个candidate,返回数组中最后那条需要删除的边。

题解:本题和上一题的不同之处在于,上一个题只是检测是否有环,这个题多了一些业务逻辑的判断,主要是一个树的一个结点不可能有两个爸爸。

如有它有两个爸爸,那么这两条边的其中之一一定是答案。

那么我们先找出来看看是否存在这种情况(一个结点有两个爸爸),parent[i] 代表 i 结点的爸爸。如果不存在这种情况,直接检测是否有环就好了。

如果存在这种情况的话,我们先删除这个结点和它第二个爸爸这条边,看剩下的边是否有环,如果有环的话,就应该返回这个结点和它第一个爸爸这条边。

 class UF {
public:
UF(int size) {
father.resize(size);
for (int i = ; i < size; ++i) {
father[i] = i;
}
}
int find(int x) {
return x == father[x] ? x : father[x] = find(father[x]);
}
void connect(int x, int y) {
int xx = find(x), yy = find(y);
if (xx == yy) { return; }
if (yy < xx) {
father[xx] = yy;
} else {
father[yy] = xx;
}
}
vector<int> father;
};
class Solution {
public:
vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
const int n = edges.size();
UF uf(n+);
vector<int> parent(n+, );
vector<int> ans1, ans2;
for (auto& e : edges) {
int p = e[], s = e[];
if (parent[s] != ) {
ans1 = {parent[s], s};
ans2 = e;
e[] = e[] = -; //先把第二条边删除,然后下面用uf检测是否有环
break;
} else {
parent[s] = p;
}
}
for (auto e : edges) {
if (e[] < && e[] < ) { continue; }
int u = uf.find(e[]), v = uf.find(e[]);
if (u == v) { //如果说在删除第二条边的情况下,有环,如果有第一条边,就返回第一条边,不然返回第二条边
if (!ans1.empty()) {return ans1;}
return e;
}
uf.connect(e[], e[]);
}
return ans2;
}
};

【721】Accounts Merge

【737】Sentence Similarity II

【765】Couples Holding Hands

【778】Swim in Rising Water

【803】Bricks Falling When Hit

【839】Similar String Groups

【928】Minimize Malware Spread II

【LeetCode】并查集 union-find(共16题)的更多相关文章

  1. [leetcode] 并查集(Ⅰ)

    预备知识 并查集 (Union Set) 一种常见的应用是计算一个图中连通分量的个数.比如: a e / \ | b c f | | d g 上图的连通分量的个数为 2 . 并查集的主要思想是在每个连 ...

  2. 并查集(Union/Find)模板及详解

    概念: 并查集是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题.一些常见的用途有求连通子图.求最小生成树的Kruskal 算法和求最近公共祖先等. 操作: 并查集的基本操作有两个 ...

  3. POJ 1611 The Suspects 并查集 Union Find

    本题也是个标准的并查集题解. 操作完并查集之后,就是要找和0节点在同一个集合的元素有多少. 注意这个操作,须要先找到0的父母节点.然后查找有多少个节点的额父母节点和0的父母节点同样. 这个时候须要对每 ...

  4. [leetcode] 并查集(Ⅱ)

    最长连续序列 题目[128]:链接. 解题思路 节点本身的值作为节点的标号,两节点相邻,即允许合并(x, y)的条件为x == y+1 . 因为数组中可能会出现值为 -1 的节点,因此不能把 root ...

  5. [leetcode] 并查集(Ⅲ)

    婴儿名字 题目[Interview-1707]:典型并查集题目. 解题思路 首先对 names 这种傻 X 字符串结构进行预处理,转换为一个 map,key 是名字,val 是名字出现的次数. 然后是 ...

  6. 一道并查集的(坑)题:关闭农场closing the farm

    题目描述 in English: Farmer John and his cows are planning to leave town for a long vacation, and so FJ ...

  7. 石头剪刀布(2019Wannafly winter camp day3 i) 带权并查集+按秩合并 好题

    题目传送门 思路: 按照题意描述,所有y挑战x的关系最后会形成一棵树的结构,n个人的总方案数是 3n 种,假设一个人被挑战(主场作战)a次,挑战别人(客场)b次,那么这个人存活到最后的方案数就是3n* ...

  8. Java 并查集Union Find

    对于一组数据,主要支持两种动作: union isConnected public interface UF { int getSize(); boolean isConnected(int p,in ...

  9. Marriage Match II(二分+并查集+最大流,好题)

    Marriage Match II http://acm.hdu.edu.cn/showproblem.php?pid=3081 Time Limit: 2000/1000 MS (Java/Othe ...

随机推荐

  1. JavaScript 函数防抖

    <!DOCTYPE html><html lang="zh-cmn-Hans"> <head> <meta charset="u ...

  2. Centos添加硬盘分区

    1. 查看硬盘信息 fdish -l 此处/dev/sdb为新添加硬盘 2. 格式化为ext4硬盘格式 mkfs.ext4 /dev/sdb 亦可使用其他格式 硬盘空间大于2T时,MBR分区无法识别更 ...

  3. js arguments参数

    在调用函数时,浏览器每次都会传递进两个隐含的参数:      1.函数的上下文对象 this      2.封装实参的对象 arguments         - arguments是一个类数组对象, ...

  4. Nginx实现反向代理与负载均衡

    1.什么是反向代理 使用nginx实现反向代理,Nginx只做请求的转发,后台有多个http服务器提供服务,nginx的功能就是把请求转发给后面的服务器,决定把请求转发给谁. 2.在一个虚拟机上创建两 ...

  5. 阿里云推出SRT+杜比全景声直播方案,低成本打造高质量直播观感体验

    超过200个国家和地区共5144万人观看:浙江卫视.东方卫视55城总收视达2.39,稳居同时段市场第一:优酷直播间63%观看晚会的用户参与了互动:微博68.2亿的主话题阅读量:2019天猫双11狂欢夜 ...

  6. 【テンプレート】RMQ

    1174 区间中最大的数 基准时间限制:1 秒 空间限制:131072 KB   收藏  关注 给出一个有N个数的序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有数中,最大的数是多少. ...

  7. Oracle 中 not exists (select 'X' ...) 的含义

    select a.col1,a.col2 from temp1 a where not exists (select 'X' from temp2 b where b.col2 = a.col1);s ...

  8. python list,dic,json型字符串转为list,dict,json

    import ast strr='{"1":"A","3":"B"}' dicts= ast.literal_eval( ...

  9. php 中 http_build_query用法

    http_build_query (PHP 5) http_build_query -- 生成 url-encoded 之后的请求字符串描述string http_build_query ( arra ...

  10. jmeter之图片上传

    用jmeter来实现图片上传请求 目录 1.抓取参数 2.填写参数 1.抓取参数 第一步:先用fiddler抓取上传接口的参数 2.填写参数 第一步:在jmeter的参数列填写没有filename的这 ...