Наименьший общий предок в бинарном поисковом дереве
Источник: https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree
Дано бинарное дерево поиска (BST), найдите вершин наименьшего общего предка (LCA), если даные 2 вершины из этого BST.
Согласно определению LCA в Википедии: «Наименьший общий предок определяется между двумя узлами p и q как наиближайшая к ним вершина в T, которая имеет как p, так и q в качестве потомков (где мы позволяем вершине быть потомком самого себя). ”
Пример 1:
Дано: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 Результат: 6 Explanation: LCA вершин 2 и 8 - это 6.
Пример 2: то же дерево, что и выше
Дано: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 Результат: 2 Explanation: LCA вершин 2 и 4 - это 2, поскольку вершина может быть потомком самой себя, согласно определнию.
Example 3:
Дано: root = [2,1], p = 2, q = 1 Output: 2
Ограничения:
- Число вершин в дереве находится в диапазоне
[2, 105]. -109 <= Node.val <= 109- Все
Node.valуникальны. p != qpиqсуществуют (не null).
Идея решения
Корень - это всегда общий предок любых других вершин в BST. Он будет LCA, если одна заданная вершина относительно корня находится в левом подереве (либо является корнем), а вторая - в правом (либо является корнем). Нам нужно минимизировать этот результат, если ни одна из вершин не является корнем.
Для этого нам нужно рассмотреть левое и правое поддерево корня.
- Если корень поддерева и есть одна из искомых вершин, то мы возвращаем этот корень поддерева.
- (рекурсивный переход) Если корень поддерева не является искомой вершиной, то рекурсивно рассматриваем его правое и левое поддерево.
- (сборка рекурсии) Если результаты левого и правого поддерева равны null, поддерево не содержит ни одной из заданой вершины, то есть поддерево с текущем корнем не может быть общим предком, и мы возвращаем null.
- Иначе рассматриваем вариации:
- если оба результата (левый и правый) не равны null, то искомые вершины находятся в разных поддеревьях - значит корень данного поддерева является общим предком.
- иначе возвращаем ненулевой результат.
Рассмотрим, например, вершины 3 и 5.
lca(3) =3, lca(5)=5,
lca(4)=4, поскольку 4.left=3, 4.right=5 и оба результата не нулевые.
Далее lca(0)=null. Значит lca(2) = nonNull(lca(0), lca(4)) = 4.
lca(8)=null. Значит lca(6) = nonNull(lca(2), lca(6)) = 4
Имплементация
В снти существует более элегантное решение, которое тоже сводится к рассмотренным случаям:
class Solution {
public TreeNode lca(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q) return root;
TreeNode left = lca(root.left, p, q);
TreeNode right = lca(root.right, p, q);
return left == null ? right : right == null ? left : root;
}
}

Комментарии
Отправить комментарий