Lowest Common Ancestor
// https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree
/*
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
Ex1:
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.
Ex2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
Ex3:
Input: root = [1,2], p = 1, q = 2
Output: 1
*/
#include <cassert>
#include <iostream>
using namespace std;
class TreeNode {
public:
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int v) {
left = nullptr;
right = nullptr;
val = v;
}
};
// Time: O(N), Space: O(H)
TreeNode* dfs(TreeNode* curr, TreeNode* p, TreeNode* q, TreeNode*& res) {
if (!curr) {
return nullptr;
}
TreeNode* l = dfs(curr->left, p, q, res);
TreeNode* r = dfs(curr->right, p, q, res);
TreeNode* currRes = nullptr;
if (l && r) {
res = curr;
} else if (!l && !r) {
if (curr->val == p->val) currRes = p;
if (curr->val == q->val) currRes = q;
} else {
TreeNode* ancestor = l ? l : r;
if (ancestor->val == p->val && curr->val == q->val) {
res = curr;
} else if (ancestor->val == q->val && curr->val == p->val) {
res = curr;
} else {
currRes = ancestor;
}
}
return currRes;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root) {
return nullptr;
}
TreeNode* res;
dfs(root, p, q, res);
return res;
}
TreeNode* lca2(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root || p == root || q == root) {
return root;
}
TreeNode* left = lca2(root->left, p, q);
TreeNode* right = lca2(root->right, p, q);
if (left && right) {
return root;
}
return left ? left : right;
}
// https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree-iii/
/*
Given two nodes of a binary tree p and q, return their lowest common ancestor (LCA).
Each node will have a reference to its parent node. The definition for Node is below:
class Node {
public int val;
public Node left;
public Node right;
public Node parent;
}
According to the definition of LCA on Wikipedia:
"The lowest common ancestor of two nodes p and q in a tree T is the lowest node that has both p and q as descendants
(where we allow a node to be a descendant of itself)."
Ex1:
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.
Ex2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5 since a node can be a descendant of itself according to the LCA definition.
Ex3:
Input: root = [1,2], p = 1, q = 2
Output: 1
*/
class Node {
public:
int val;
Node* left;
Node* right;
Node* parent;
};
// Time: O(logN), Space: O(logN)
Node* lca_iii(Node* p, Node* q) {
unordered_map<int, Node*> m;
while (p) {
m[p->val] = p;
p = p->parent;
}
while (q) {
if (m.count(q->val)) {
return q;
}
q = q->parent;
}
return nullptr;
}
// Time: O(logN), Space: O(1)
Node* lca_iii_trick(Node* p, Node* q) {
Node* a = p, * b = q;
while (a != b) {
a = (a == nullptr ? q : a->parent);
b = (b == nullptr ? p : b->parent);
}
return a;
}
int main() {
// Test case 1: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
TreeNode* root1 = new TreeNode(3);
root1->left = new TreeNode(5);
root1->right = new TreeNode(1);
root1->left->left = new TreeNode(6);
root1->left->right = new TreeNode(2);
root1->right->left = new TreeNode(0);
root1->right->right = new TreeNode(8);
root1->left->right->left = new TreeNode(7);
root1->left->right->right = new TreeNode(4);
assert(lowestCommonAncestor(root1, root1->left, root1->right)->val == 3);
// Test case 2: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
TreeNode* root2 = root1; // Reuse the same tree
assert(lowestCommonAncestor(root2, root2->left, root2->left->right->right)->val == 5);
// Test case 3: root = [1,2], p = 1, q = 2
TreeNode* root3 = new TreeNode(1);
root3->left = new TreeNode(2);
assert(lowestCommonAncestor(root3, root3, root3->left)->val == 1);
return 0;
}```
Last updated