Я попал в статью, в которой рассказывается об алгоритмах LCA, код простой http://leetcode.com /2011/07/lowest-common-ancestor-of-a-binary-tree-part-i.html
// Return #nodes that matches P or Q in the subtree.
int countMatchesPQ(Node *root, Node *p, Node *q) {
if (!root) return 0;
int matches = countMatchesPQ(root->left, p, q) + countMatchesPQ(root->right, p, q);
if (root == p || root == q)
return 1 + matches;
else
return matches;
}
Node *LCA(Node *root, Node *p, Node *q) {
if (!root || !p || !q) return NULL;
if (root == p || root == q) return root;
int totalMatches = countMatchesPQ(root->left, p, q);
if (totalMatches == 1)
return root;
else if (totalMatches == 2)
return LCA(root->left, p, q);
else /* totalMatches == 0 */
return LCA(root->right, p, q);
}
Но мне было интересно, как вычислить временную сложность алгоритма, может ли кто-нибудь мне помочь?
2 ответа
Наихудший случай для этого алгоритма был бы, если бы узлы были выходными узлами одного и того же уровня.
Node *LCA(Node *root, Node *p, Node *q)
{
for root call countMatchesPQ;
for(root->left_or_right_child) call countMatchesPQ; /* Recursive call */
for(root->left_or_right_child->left_or_right_child) call countMatchesPQ;
...
for(parent of leave nodes of p and q) call countMatchesPQ;
}
countMatchesPQ
вызывается для height of tree times - 1
. Назовем высоту дерева как h
.
Теперь проверьте сложность вспомогательной функции
int countMatchesPQ(Node *root, Node *p, Node *q) {
Search p and q in left sub tree recursively
Search p and q in right sub tree recursively
}
Итак, это обширный поиск, и последняя сложность составляет N
, где N
- количество узлов в дереве.
Сложив оба наблюдения, общая сложность алгоритма составит
O(h * N)
Если дерево сбалансировано, h = log N
(дерево RB, treap и т. Д.) Если дерево неуравновешено, в худшем случае h may be up to N
Таким образом, сложность с точки зрения N
может быть задана как
Для сбалансированного двоичного дерева: O (N logN)
Точнее, это действительно h (N + N / 2 + N / 4 ...) для сбалансированного дерева и, следовательно, должно получиться 2hN
Для несбалансированного двоичного дерева: O (N 2 )
Точнее, это действительно h (N + N-1 + N-2 ...) для сбалансированного дерева и, следовательно, должно быть h x N x (N + 1) / 2
2
Ваш алгоритм не использует память. Используя некоторую память для сохранения пути, вы можете значительно улучшить свой алгоритм.
Сложность LCA составляет O(h)
, где h
- высота дерева. Верхняя граница высоты дерева равна O(n)
, где n
обозначает количество вершин / узлов в дереве.
Если ваше дерево сбалансировано (см. AVL, красно-черное дерево) высота порядка log(n)
, следовательно, общая сложность алгоритма равна O(log(n))
.
h
раз) в функции countMatchesPQ. Таким образом, общая сложность должна быть больше, чем h. Не так ли?
Похожие вопросы
Связанные вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.