注意这题一共有三种情况构不成树,一是有环,二是有入度为2的节点,三是又有环又有出度为2的节点
用一个并查集检查是否有环,遍历的同时自身判断是否存在冲突
class UnionSet:
def __init__(self,n):
self.ancestor = list(range(n))
def find(self,x):
if x != self.ancestor[x]:
self.ancestor[x] = self.find(self.ancestor[x])
return self.ancestor[x]
def union(self,index1,index2):
self.ancestor[self.find(index1)] = self.find(index2)
class Solution(object):
def findRedundantDirectedConnection(self, edges):
"""
:type edges: List[List[int]]
:rtype: List[int]
"""
n = len(edges) + 1
uf = UnionSet(n) #实例化一个并查集
parent = list(range(n))
conflict = -1
cycle = -1
for i, (node1,node2) in enumerate(edges):
if parent[node2] != node2: #两个爹,这里相当于node2的入度为2。因为第一次遇到这个node2时他肯定等于自己,后面第二次遇到时相当于入度为2,产生冲突
conflict = i
else:
parent[node2] = node1 #根据edges更新父节点即node1->node2
if uf.find(node1) == uf.find(node2): #这是实例uf的,没合并之前就一个爹,说明有环
cycle = i
else:
uf.union(node1,node2) #还没遇到错误,合并
if conflict < 0:
return edges[cycle] #没有冲突,直接返回构成环的那条边就是最后一个
else: #有冲突需要检查有没有环
conflictedges = edges[conflict]
if cycle >= 0:
return [parent[conflictedges[1]],conflictedges[1]] #既有冲突又有环的时候需要消除这个冲突还有环,所以找入度为2的节点和他的父节点,因为指向是从父节点指向子节点,只有这样能同时消除环和冲突
else:
return conflictedges #没环直接返回冲突那条边