Как уже упоминалось, ваш алгоритм в настоящее время является квадратичным.Это не может быть проблемой для набора данных размером от 50 до 75 узлов, но в любом случае просто изменить его на линейное время без использования каких-либо наборов или хеш-таблиц, просто записав полный путь к корню для каждого узла, затемспускаясь вниз от корня и ища первый другой узел.Затем непосредственно предшествующий узел (который является общим родителем этих 2 разных узлов) - это LCA:
linearLCA(node1, node2) {
parentNode1 := [ ]
while (node1!=NULL) {
parentNode1.push(node1)
node1 := node1.parent
}
parentNode2 := [ ]
while (node2!=NULL) {
parentNode2.push(node2)
node2 := node2.parent
}
while (node1 == node2 && !isEmpty(parentNode1) && !isEmpty(parentNode2)) {
oldNode := node1
node1 := parentNode1.pop()
node2 := parentNode2.pop()
}
if (node1 == node2) return node1 // One node is descended from the other
else return oldNode // Neither is descended from the other
}
РЕДАКТИРОВАТЬ 27/5/2012: Обработать случай, в котором один узелпроисходит от другого, что в противном случае привело бы к попытке pop()
пустого стека.Спасибо, черт побери, за то, что указал на это.(Я также понял, что достаточно отследить один oldNode
.)