Это не «путешественник» (который посещает каждый узел в дереве); то, что вы описываете, просто следует за родителями.
Алгоритм будет выглядеть следующим образом. Одним из приемов является чередование вычислений, так что алгоритм гарантированно быстро завершится. Вы также должны рассмотреть такие случаи, как node1==node2
. Это также алгоритм O(A+B=N)
, а не O(A*B=N^2)
, где мы учитываем расстояние между узлами и их самым младшим общим предком.
def findYoungestCommonAncestor(node1, node2):
visited = set()
if node1==node2:
return node1
while True:
if node1 in visited:
return node1
if node2 in visited:
return node2
if not node1.parent and not node2.parent:
return None
if node1.parent:
visited.add(node1)
node1 = node1.parent
if node2.parent:
visited.add(node2)
node2 = node2.parent
Узлы node1
и node2
могут быть частью леса (набора связанных деревьев), и это все равно должно работать.
Более элегантно было бы что-то вроде:
def ancestors(node):
"""
an iterator of node, node.parent, node.parent.parent...
"""
yield node
while node.parent:
yield node
node = node.parent
def interleave(*iters):
"""
interleave(range(3), range(10,16)) -> 0,10,1,11,2,12,13,14,15
"""
ignore = object()
for tuple in zip_longest(*iters, fillvalue=ignore):
for x in tuple:
if not x is ignore:
yield x
def findYoungestCommonAncestor(node1, node2):
# implementation: find first repeated value in interleaved ancestors
visited = set()
for node in interleave(ancestors(node1), ancestors(node2)):
if node in visited:
return node
else:
visited.add(node)