不管全世界所有人怎么说,我都认为自己的感受才是正确的。无论别人怎么看,我绝不打乱自己的节奏。喜欢的事自然可以坚持,不喜欢的怎么也长久不了。
LeetCode:原题地址
题目要求
在本问题中,有根树指满足以下条件的 有向 图。该树只有一个根节点,所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点。
输入一个有向图,该图由一个有着 n 个节点(节点值不重复,从 1 到 n)的树及一条附加的有向边构成。附加的边包含在 1 到 n 中的两个不同顶点间,这条附加的边不属于树中已存在的边。
结果图是一个以边组成的二维数组 edges 。 每个元素是一对 [ui, vi],用以表示 有向 图中连接顶点 ui 和顶点 vi 的边,其中 ui 是 vi 的一个父节点。
返回一条能删除的边,使得剩下的图是有 n 个节点的有根树。若有多个答案,返回最后出现在给定二维数组的答案。
示例 1:
输入: edges = [[1,2],[1,3],[2,3]]
输出: [2,3]
示例 2:
输入: edges = [[1,2],[2,3],[3,4],[4,1],[1,5]]
输出: [4,1]
提示:
n == edges.length3 <= n <= 1000edges[i].length == 21 <= ui, vi <= n
思路
利用并查集,先查出入度为2的点和边 再删除这些边判断能否生成树(如果删除边后两个点根节点不一样就不能生成树)
如果没有入度为2的点就去判断生成环路的边删除
/**
* @param {number[][]} edges
* @return {number[]}
*/
var findRedundantDirectedConnection = function(edges) {
let inDegree = []; // 记录节点入度
let vec = [] // 记录边
let un = new UnionFind(edges.length)
for(let i = 0; i <= edges.length;i++) {
inDegree[i] = 0
}
for (let i = 0; i < edges.length; i++) {
inDegree[edges[i][1]]++; // 统计入度
}
for (let i = edges.length - 1; i >= 0; i--) {
if (inDegree[edges[i][1]] == 2) {
vec.push(edges[i]);
}
}
if(vec.length) {
// 删除入度为2的边
if(isTreeAfterRemoveEdge(edges,vec[0])) {
return vec[0]
}
return vec[1]
} else {
// 判断环路
for(let i = 0; i < edges.length;i++){
if(un.union(edges[i][0],edges[i][1])) {
return edges[i]
}
}
}
function isTreeAfterRemoveEdge(edges, deleteEdge) {
for(let i = 0; i < edges.length;i++){
if(edges[i] == deleteEdge) continue;
un.union(edges[i][0],edges[i][1])
}
if(un.find(deleteEdge[0]) == un.find(deleteEdge[1])) {
return true
}
return false
}
};
class UnionFind{
constructor(n){
this.rank = []
this.parent = []
for(let i = 0;i<=n;i++){
this.parent[i] = i;
this.rank[i] = 0;
}
}
find(index){
if(this.parent[index] != index){
this.parent[index] = this.find(this.parent[index]);
}
return this.parent[index];
}
union(x,y){
let x_root = this.find(x)
let y_root = this.find(y)
if(x_root == y_root) {
return [x,y]
}else {
if(this.rank[x_root]>this.rank[y_root]) {
this.parent[y_root] = x_root
}else if(this.rank[x_root]<this.rank[y_root]){
this.parent[x_root] = y_root
}else {
this.parent[x_root] = y_root
this.rank[y_root]++
}
}
}
}