236. Lowest Common Ancestor of a Binary Tree
leetcode medium
Task
Дано бинарное дерево. Найдите наименьший общий предок (LCA) двух заданных узлов в дереве.
Согласно определению LCA на Википедии: "Наименьший общий предок определяется между двумя узлами p и q как наименьший узел в дереве T, который имеет как p, так и q в качестве потомков (где мы допускаем, что узел может быть потомком самого себя)."
Пример
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.
C# solution
matched/originalpublic class Solution {
private TreeNode ans;
public Solution() {
this.ans = null;
}
private bool RecurseTree(TreeNode currentNode, TreeNode p, TreeNode q) {
if (currentNode == null) {
return false;
}
int left = this.RecurseTree(currentNode.left, p, q) ? 1 : 0;
int right = this.RecurseTree(currentNode.right, p, q) ? 1 : 0;
int mid = (currentNode == p || currentNode == q) ? 1 : 0;
if (mid + left + right >= 2) {
this.ans = currentNode;
}
return (mid + left + right > 0);
}
public TreeNode LowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
this.RecurseTree(root, p, q);
return this.ans;
}
}C++ solution
auto-draft, review before submit#include <bits/stdc++.h>
using namespace std;
// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
private TreeNode ans;
public Solution() {
this.ans = null;
}
private bool RecurseTree(TreeNode currentNode, TreeNode p, TreeNode q) {
if (currentNode == null) {
return false;
}
int left = this.RecurseTree(currentNode.left, p, q) ? 1 : 0;
int right = this.RecurseTree(currentNode.right, p, q) ? 1 : 0;
int mid = (currentNode == p || currentNode == q) ? 1 : 0;
if (mid + left + right >= 2) {
this.ans = currentNode;
}
return (mid + left + right > 0);
}
public TreeNode LowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
this.RecurseTree(root, p, q);
return this.ans;
}
}Java solution
matched/originalclass Solution {
private TreeNode ans;
public Solution() {
this.ans = null;
}
private boolean recurseTree(TreeNode currentNode, TreeNode p, TreeNode q) {
if (currentNode == null) {
return false;
}
int left = this.recurseTree(currentNode.left, p, q) ? 1 : 0;
int right = this.recurseTree(currentNode.right, p, q) ? 1 : 0;
int mid = (currentNode == p || currentNode == q) ? 1 : 0;
if (mid + left + right >= 2) {
this.ans = currentNode;
}
return (mid + left + right > 0);
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
this.recurseTree(root, p, q);
return this.ans;
}
}JavaScript solution
matched/originalclass Solution {
constructor() {
this.ans = null;
}
recurseTree(currentNode, p, q) {
if (currentNode === null) {
return false;
}
const left = this.recurseTree(currentNode.left, p, q) ? 1 : 0;
const right = this.recurseTree(currentNode.right, p, q) ? 1 : 0;
const mid = (currentNode === p || currentNode === q) ? 1 : 0;
if (mid + left + right >= 2) {
this.ans = currentNode;
}
return (mid + left + right > 0);
}
lowestCommonAncestor(root, p, q) {
this.recurseTree(root, p, q);
return this.ans;
}
}Python solution
matched/originalclass Solution:
def __init__(self):
self.ans = None
def recurseTree(self, currentNode, p, q):
if not currentNode:
return False
left = self.recurseTree(currentNode.left, p, q) ? 1 : 0
right = self.recurseTree(currentNode.right, p, q) ? 1 : 0
mid = (currentNode == p or currentNode == q) ? 1 : 0
if mid + left + right >= 2:
self.ans = currentNode
return mid + left + right > 0
def lowestCommonAncestor(self, root, p, q):
self.recurseTree(root, p, q)
return self.ansGo solution
matched/originaltype TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
type Solution struct {
ans *TreeNode
}
func Constructor() Solution {
return Solution{ans: nil}
}
func (this *Solution) recurseTree(currentNode, p, q *TreeNode) bool {
if currentNode == nil {
return false
}
left := 0
if this.recurseTree(currentNode.Left, p, q) {
left = 1
}
right := 0
if this.recurseTree(currentNode.Right, p, q) {
right = 1
}
mid := 0
if currentNode == p || currentNode == q {
mid = 1
}
if mid+left+right >= 2 {
this.ans = currentNode
}
return mid+left+right > 0
}
func (this *Solution) LowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
this.recurseTree(root, p, q)
return this.ans
}Explanation
Algorithm
Начало обхода дерева с корня: Начните обход дерева с корневого узла. Если текущий узел является одним из узлов p или q, установите переменную mid в значение True и продолжите поиск другого узла в левой и правой ветвях.
Проверка поддеревьев: Выполните рекурсивный обход левой и правой ветвей дерева. Если какая-либо из ветвей (левая или правая) возвращает True, это означает, что один из двух узлов найден ниже по дереву.
Определение LCA: Если в любой момент обхода дерева две из трех переменных (left, right или mid) становятся True, это означает, что найден наименьший общий предок (LCA) для узлов p и q.
😎