题目描述
解题思路
对于冗余连接,共有 3 种情况:
一个节点有两个 parent,
移除第二个边
有环
移除一个边
环 + 两个 parent
移除 [2 ,3]
详细解释第三种
可以看到,我们总是根据题意去移除第二个边,那么如果在移除这条边后发现,剩下的边会形成环,我们就应该移除第一个边
If [[1, 2], [2, 3], [4, 3], [3, 1]], [2, 3] 在 [4, 3] 之前, 移除 [4,3], union [1, 2], [2, 3], [3, 1], 有环 -- 应移除的其实是 [2, 3].
If [[1, 2], [4, 3], [2, 3], [3, 1]], [4, 3] 在 [2, 3] 之前, 移除 [2, 3], union [1, 2], [4, 3], [3, 1], 没有环 -- 移除 [2, 3] 是正确的.
代码
function findRedundantDirectedConnection(edges) {
let numNodes = edges.length,
edgeRemoved = -1,
edgeMakesCycle = -1
const parent = new Array(numNodes + 1).fill(0)
for (let i = 0; i < numNodes; i++) {
const u = edges[i][0]
const v = edges[i][1]
if (parent[v] != 0) {
/* Assume we removed the second edge. */
edgeRemoved = i
break
} else parent[v] = u
}
const uf = new UnionFind(numNodes)
for (let i = 0; i < numNodes; i++) {
if (i == edgeRemoved) continue
const u = edges[i][0]
const v = edges[i][1]
if (!uf.union(u, v)) {
edgeMakesCycle = i
break
}
}
/* Handle with the cyclic problem only. */
if (edgeRemoved == -1) {
return edges[edgeMakesCycle]
}
/* Handle with the cyclic problem when we remove the wrong edge. */
if (edgeMakesCycle != -1) {
const v = edges[edgeRemoved][1]
const u = parent[v]
return [u, v]
}
/* CHandle with the cyclic problem when we remove the right edge. */
return edges[edgeRemoved]
}
class UnionFind {
constructor(n) {
this.parent = new Array(n + 1)
this.rank = new Array(n + 1)
for (let i = 1; i < n + 1; i++) {
this.parent[i] = i
this.rank[i] = 1
}
}
find = (x) => {
const parent = this.parent
const find = this.find
if (parent[x] == x) return x
return (parent[x] = find(parent[x]))
}
union = (x, y) => {
const rootX = this.find(x)
const rootY = this.find(y)
const parent = this.parent
const rank = this.rank
if (rootX == rootY) return false
if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY
rank[rootY] += rank[rootX]
} else {
parent[rootY] = rootX
rank[rootX] += rank[rootY]
}
return true
}
}