Вот алгоритм, который я придумал для нерекурсивного нахождения младшего общего предка двух узлов в двоичном дереве. Вот основная стратегия:Самая быстрая нерекурсивная реализация LCA?
- Используйте словарь/хеш-таблицу для хранения дерева. Каждая пара ключ-значение представляет собой узел и его родительский элемент.
- Начиная с каждого из двух узлов, поднимитесь по дереву, установив переменную, представляющую значение каждого узла, в значение родительского элемента, сохраняя пройденные значения в хэш-наборе (по одному для каждого из двух узлов).
- Поиск завершен при достижении любого из следующих условий: (a) значение двух узлов равно; или (b) когда два пути пересекаются друг с другом (то есть, хешсет перемещенных значений узла 1 содержит текущее значение для узла 2 или наоборот); или (c) переданный узел не существует в дереве (в этом случае алгоритм завершается и возвращает -1).
Мое понимание заключается в том, что наихудшая временная и пространственная сложность моего алгоритма - это O (log (n)), так как нам никогда не нужно совершать более 2 * дорожек по высоте или хранить более 2 * значений высоты в наших хэшсетах (и поскольку время поиска для хешсет и словаря дерева - O (1)).
Следующий мой код (C#). Пожалуйста, сообщите, если я правильно в моем анализе, или если есть более эффективный (нерекурсивный) способ сделать это:
int LowestCommonAncestor(int value1, int value2, Dictionary<int, int> tree)
{
var value1Visited = new HashSet<int>();
var value2Visited = new HashSet<int>();
while (true)
{
if (value1 == value2) return value1;
if (value1Visited.Contains(value2)) return value2;
if (value2Visited.Contains(value1)) return value1;
int nextValue1;
int nextValue2;
if (tree.TryGetValue(value1, out nextValue1))
{
//Walk node 1 up the tree:
value1 = nextValue1;
value1Visited.Add(value1);
}
else
{
//Node doesn't exist in tree:
return -1;
}
if (tree.TryGetValue(value2, out nextValue2))
{
//Walk node 2 up the tree:
value2 = nextValue2;
value2Visited.Add(value2);
}
else
{
//Node doesn't exist in tree:
return -1;
}
}
}
ли предложенный алгоритм вызвать некоторые ошибки или неожиданные результаты? –
Это не 'O (log N)', если дерево не сбалансировано. Это 'O (N)' (например, бамбук - это двоичное дерево). – kraskevich