[LeetCode] Redundant Connection 冗余的连接
In this problem, a tree is an undirected graph that is connected and has no cycles.
The given input is a graph that started as a tree with N nodes (with distinct values 1, 2, ..., N), with one additional edge added. The added edge has two different vertices chosen from 1 to N, and was not an edge that already existed.
The resulting graph is given as a 2D-array of edges. Each element of edges is a pair [u, v] with u < v, that represents an undirected edge connecting nodes u and v.
Return an edge that can be removed so that the resulting graph is a tree of N nodes. If there are multiple answers, return the answer that occurs last in the given 2D-array. The answer edge [u, v] should be in the same format, with u < v.
Example 1:
Input: [[1,2], [1,3], [2,3]]
Output: [2,3]
Explanation: The given undirected graph will be like this:
1
/ \
2 - 3
Example 2:
Input: [[1,2], [2,3], [3,4], [1,4], [1,5]]
Output: [1,4]
Explanation: The given undirected graph will be like this:
5 - 1 - 2
| |
4 - 3
Note:
- The size of the input 2D-array will be between 3 and 1000.
- Every integer represented in the 2D-array will be between 1 and N, where N is the size of the input array.
Update (2017-09-26):
We have overhauled the problem description + test cases and specified clearly the graph is an undirected graph. For the directedgraph follow up please see Redundant Connection II). We apologize for any inconvenience caused.
这道题给我们了一个无向图,让删掉组成环的最后一条边,其实这道题跟之前那道 Graph Valid Tree 基本没什么区别,三种解法都基本相同。博主觉得老题稍微变一下就是一道新题,而 onsite 遇到原题的概率很小,大多情况下都会稍稍变一下,所以举一反三的能力真的很重要,要完全吃透一道题也不太容易,需要多下功夫。首先来看递归的解法,这种解法的思路是,每加入一条边,就进行环检测,一旦发现了环,就返回当前边。对于无向图,还是用邻接表来保存,建立每个结点和其所有邻接点的映射,由于两个结点之间不算有环,所以要避免这种情况 1->{2}, 2->{1} 的死循环,用一个变量 pre 记录上一次递归的结点,比如上一次遍历的是结点1,那么在遍历结点2的邻接表时,就不会再次进入结点1了,这样有效的避免了死循环,使其能返回正确的结果,参见代码如下:
解法一:
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
unordered_map<int, unordered_set<int>> m;
for (auto edge : edges) {
if (hasCycle(edge[], edge[], m, -)) return edge;
m[edge[]].insert(edge[]);
m[edge[]].insert(edge[]);
}
return {};
}
bool hasCycle(int cur, int target, unordered_map<int, unordered_set<int>>& m, int pre) {
if (m[cur].count(target)) return true;
for (int num : m[cur]) {
if (num == pre) continue;
if (hasCycle(num, target, m, cur)) return true;
}
return false;
}
};
既然递归能做,一般来说迭代也木有问题。但是由于 BFS 的遍历机制和 DFS 不同,所以没法采用利用变量 pre 来避免上面所说的死循环(不是很确定,可能是博主没想出来,有做出来的请在评论区贴上代码),所以采用一个集合来记录遍历过的结点,如果该结点已经遍历过了,那么直接跳过即可,否则就把该结点加入 queue 和集合,继续循环,参见代码如下:
解法二:
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
unordered_map<int, unordered_set<int>> m;
for (auto edge : edges) {
queue<int> q{{edge[]}};
unordered_set<int> s{{edge[]}};
while (!q.empty()) {
auto t = q.front(); q.pop();
if (m[t].count(edge[])) return edge;
for (int num : m[t]) {
if (s.count(num)) continue;
q.push(num);
s.insert(num);
}
}
m[edge[]].insert(edge[]);
m[edge[]].insert(edge[]);
}
return {};
}
};
其实这道题最好的解法使用 Union Find 来做,论坛上清一色的都是用这种解法来做的,像博主用 DFS 和 BFS 这么清新脱俗的方法还真不多:) 其实 Union Find 的核心思想并不是很难理解,首先建立一个长度为 (n+1) 的数组 root,由于这道题并没有明确的说明n是多少,只是说了输入的二位数组的长度不超过 1000,那么n绝对不会超过 2000,加1的原因是由于结点值是从1开始的,而数组是从0开始的,懒得转换了,就多加一位得了。将这个数组都初始化为 -1,有些人喜欢初始化为i,都可以。开始表示每个结点都是一个单独的组,所谓的 Union Find 就是要让结点之间建立关联,比如若 root[1] = 2,就表示结点1和结点2是相连的,root[2] = 3 表示结点2和结点3是相连的,如果此时新加一条边 [1, 3] 的话,我们通过 root[1] 得到2,再通过 root[2] 得到3,说明结点1有另一条路径能到结点3,这样就说明环是存在的;如果没有这条路径,那么要将结点1和结点3关联起来,让 root[1] = 3 即可,参见代码如下:
解法三:
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
vector<int> root(, -);
for (auto edge : edges) {
int x = find(root, edge[]), y = find(root, edge[]);
if (x == y) return edge;
root[x] = y;
}
return {};
}
int find(vector<int>& root, int i) {
while (root[i] != -) {
i = root[i];
}
return i;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/684
类似题目:
Number of Connected Components in an Undirected Graph
参考资料:
https://leetcode.com/problems/redundant-connection/
https://leetcode.com/problems/redundant-connection/discuss/112562/My-DFS-and-BSF-solutions
https://leetcode.com/problems/redundant-connection/discuss/107984/10-line-Java-solution-Union-Find.
https://leetcode.com/problems/redundant-connection/discuss/108010/C%2B%2B-solution-using-union-find
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Redundant Connection 冗余的连接的更多相关文章
- [LeetCode] 684. Redundant Connection 冗余的连接
In this problem, a tree is an undirected graph that is connected and has no cycles. The given input ...
- [LeetCode] Redundant Connection II 冗余的连接之二
In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) f ...
- LeetCode 684. Redundant Connection 冗余连接(C++/Java)
题目: In this problem, a tree is an undirected graph that is connected and has no cycles. The given in ...
- [LeetCode] 685. Redundant Connection II 冗余的连接之 II
In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) f ...
- Leetcode之并查集专题-684. 冗余连接(Redundant Connection)
Leetcode之并查集专题-684. 冗余连接(Redundant Connection) 在本问题中, 树指的是一个连通且无环的无向图. 输入一个图,该图由一个有着N个节点 (节点值不重复1, 2 ...
- [LeetCode] 685. Redundant Connection II 冗余的连接之二
In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) f ...
- [Swift]LeetCode684. 冗余连接 | Redundant Connection
In this problem, a tree is an undirected graph that is connected and has no cycles. The given input ...
- LeetCode 685. Redundant Connection II
原题链接在这里:https://leetcode.com/problems/redundant-connection-ii/ 题目: In this problem, a rooted tree is ...
- LN : leetcode 684 Redundant Connection
lc 684 Redundant Connection 684 Redundant Connection In this problem, a tree is an undirected graph ...
随机推荐
- Java多线程:CopyOnWrite容器
一.什么是CopyOnWrite容器 CopyOnWrite容器即写时复制的容器.通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然 ...
- Oracle查看表空间大小和使用率
1. 全部表空间的大小select tablespace_name, sum(bytes)/1024/1024 from dba_data_files group by tablespace_name ...
- 漫谈Java IO之 NIO那些事儿
前面一篇中已经介绍了基本IO的使用以及最简单的阻塞服务器的例子,本篇就来介绍下NIO的相关内容,前面的分享可以参考目录: 网络IO的基本知识与概念 普通IO以及BIO服务器 NIO的使用与服务器Hel ...
- 使用Java客户端操作elasticsearch
Java REST客户端有两种风格: Java低级别REST客户端(Java Low Level REST Client,以后都简称低级客户端算了,难得码字):Elasticsearch的官方low- ...
- 利用PCA降维
参考:<机器学习实战>- Machine Learning in Action 一. 基本思想 PCA(Principal Component Analysis),主成分分析.是目前应用 ...
- Python实现基于协程的异步爬虫
一.课程介绍 1. 课程来源 本课程核心部分来自<500 lines or less>项目,作者是来自 MongoDB 的工程师 A. Jesse Jiryu Davis 与 Python ...
- 《高级软件测试》JIRA使用手册(二)JIRA安装
Jira Software 下载地址 Windows系统x86平台:https://downloads.atlassian.com/software/jira/downloads/atlassian- ...
- css变化代码2
<!DOCTYPE html><html> <head> <meta charset="utf-8" /> ...
- 如何书写高效的css样式
如何书写高效的css样式? 有以下四个关键要素: 1.高效的css 2.可维护的css 3.组件化的css 4.hack-free css 书写高效的css: 1.使用外联样式替代行间样式或内嵌样式 ...
- recompose mapProps
mapProps介绍 mapProps函数接收一个函数参数,这个函数参数会返回一个对象用作为接下来的组件的props.组件接收到的props只能是通过mapProps函数参数返回的对象,其他的prop ...