TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
auto pathTo = [&](TreeNode* target) -> vector<TreeNode*> {
vector<TreeNode*> path;
function<bool(TreeNode*)> dfs = [&](TreeNode* node) -> bool {
if (!node) return false;
path.push_back(node);
if (node == target || dfs(node->left) || dfs(node->right)) return true;
path.pop_back();
return false;
};
if (!dfs(root)) path.clear();
return path;
};
vector<TreeNode*> a = pathTo(p);
vector<TreeNode*> b = pathTo(q);
if (a.empty() || b.empty()) return nullptr;
TreeNode* lca = nullptr;
for (size_t i = 0; i < min(a.size(), b.size()) && a[i] == b[i]; i++) lca = a[i];
return lca;
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
List<TreeNode> a = pathTo(root, p);
List<TreeNode> b = pathTo(root, q);
if (a == null || b == null) return null;
TreeNode lca = null;
for (int i = 0; i < Math.min(a.size(), b.size()) && a.get(i) == b.get(i); i++) lca = a.get(i);
return lca;
}
private List<TreeNode> pathTo(TreeNode root, TreeNode target) {
List<TreeNode> path = new ArrayList<>();
return dfs(root, target, path) ? path : null;
}
private boolean dfs(TreeNode node, TreeNode target, List<TreeNode> path) {
if (node == null) return false;
path.add(node);
if (node == target || dfs(node.left, target, path) || dfs(node.right, target, path)) return true;
path.remove(path.size() - 1);
return false;
}
def lowest_common_ancestor(root, p, q):
def path_to(target):
path = []
def dfs(node):
if not node: return False
path.append(node)
if node is target or dfs(node.left) or dfs(node.right): return True
path.pop()
return False
return path if dfs(root) else None
a = path_to(p)
b = path_to(q)
if a is None or b is None: return None
lca = None
for x, y in zip(a, b):
if x is not y: break
lca = x
return lca
function lowestCommonAncestor(root: TreeNode | null, p: TreeNode, q: TreeNode): TreeNode | null {
const pathTo = (target: TreeNode): TreeNode[] | null => {
const path: TreeNode[] = [];
const dfs = (node: TreeNode | null): boolean => {
if (!node) return false;
path.push(node);
if (node === target || dfs(node.left) || dfs(node.right)) return true;
path.pop();
return false;
};
return dfs(root) ? path : null;
};
const a = pathTo(p);
const b = pathTo(q);
if (!a || !b) return null;
let lca: TreeNode | null = null;
for (let i = 0; i < Math.min(a.length, b.length) && a[i] === b[i]; i++) lca = a[i];
return lca;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root) return nullptr;
unordered_map<TreeNode*, TreeNode*> parent{{root, nullptr}};
queue<TreeNode*> pending; pending.push(root);
while (!parent.count(p) || !parent.count(q)) {
TreeNode* node = pending.empty() ? nullptr : pending.front();
if (!node) return nullptr;
pending.pop();
if (node->left) { parent[node->left] = node; pending.push(node->left); }
if (node->right) { parent[node->right] = node; pending.push(node->right); }
}
unordered_set<TreeNode*> ancestors;
for (TreeNode* cur = p; cur; cur = parent[cur]) ancestors.insert(cur);
for (TreeNode* cur = q; cur; cur = parent[cur]) {
if (ancestors.count(cur)) return cur;
}
return nullptr;
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) return null;
Map<TreeNode, TreeNode> parent = new HashMap<>(); parent.put(root, null);
Deque<TreeNode> queue = new ArrayDeque<>(); queue.add(root);
while (!parent.containsKey(p) || !parent.containsKey(q)) {
TreeNode node = queue.poll();
if (node == null) return null;
if (node.left != null) { parent.put(node.left, node); queue.add(node.left); }
if (node.right != null) { parent.put(node.right, node); queue.add(node.right); }
}
Set<TreeNode> ancestors = new HashSet<>();
for (TreeNode cur = p; cur != null; cur = parent.get(cur)) ancestors.add(cur);
for (TreeNode cur = q; cur != null; cur = parent.get(cur)) {
if (ancestors.contains(cur)) return cur;
}
return null;
}
def lowest_common_ancestor(root, p, q):
if not root: return None
parent = {root: None}
queue = deque([root])
while p not in parent or q not in parent:
node = queue.popleft() if queue else None
if not node: return None
if node.left: parent[node.left] = node; queue.append(node.left)
if node.right: parent[node.right] = node; queue.append(node.right)
ancestors = set()
cur = p
while cur: ancestors.add(cur); cur = parent.get(cur)
cur = q
while cur:
if cur in ancestors: return cur
cur = parent.get(cur)
return None
function lowestCommonAncestor(root: TreeNode | null, p: TreeNode, q: TreeNode): TreeNode | null {
if (!root) return null;
const parent = new Map<TreeNode, TreeNode | null>([[root, null]]);
const queue: TreeNode[] = [root];
while (!parent.has(p) || !parent.has(q)) {
const node = queue.shift();
if (!node) return null;
if (node.left) { parent.set(node.left, node); queue.push(node.left); }
if (node.right) { parent.set(node.right, node); queue.push(node.right); }
}
const ancestors = new Set<TreeNode>();
for (let cur: TreeNode | null = p; cur; cur = parent.get(cur) ?? null) ancestors.add(cur);
for (let cur: TreeNode | null = q; cur; cur = parent.get(cur) ?? null) {
if (ancestors.has(cur)) return cur;
}
return null;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root || root == p || root == q) return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if (left && right) return root;
return left ? left : right;
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q) return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left != null && right != null) return root;
return left != null ? left : right;
}
def lowest_common_ancestor(root, p, q):
if not root or root is p or root is q: return root
left = lowest_common_ancestor(root.left, p, q)
right = lowest_common_ancestor(root.right, p, q)
if left and right: return root
return left or right
function lowestCommonAncestor(root: TreeNode | null, p: TreeNode, q: TreeNode): TreeNode | null {
if (!root || root === p || root === q) return root;
const left = lowestCommonAncestor(root.left, p, q);
const right = lowestCommonAncestor(root.right, p, q);
if (left && right) return root;
return left ?? right;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
bool foundP = false, foundQ = false;
function<TreeNode*(TreeNode*)> dfs = [&](TreeNode* node) -> TreeNode* {
if (!node) return nullptr;
TreeNode* left = dfs(node->left);
TreeNode* right = dfs(node->right);
if (node == p) foundP = true;
if (node == q) foundQ = true;
if (node == p || node == q) return node;
if (left && right) return node;
return left ? left : right;
};
TreeNode* lca = dfs(root);
return foundP && foundQ ? lca : nullptr;
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
boolean[] found = new boolean[2];
TreeNode lca = dfs(root, p, q, found);
return found[0] && found[1] ? lca : null;
}
private TreeNode dfs(TreeNode node, TreeNode p, TreeNode q, boolean[] found) {
if (node == null) return null;
TreeNode left = dfs(node.left, p, q, found);
TreeNode right = dfs(node.right, p, q, found);
if (node == p) found[0] = true;
if (node == q) found[1] = true;
if (node == p || node == q) return node;
if (left != null && right != null) return node;
return left != null ? left : right;
}
def lowest_common_ancestor(root, p, q):
found_p = found_q = False
def dfs(node):
nonlocal found_p, found_q
if not node: return None
left = dfs(node.left)
right = dfs(node.right)
if node is p: found_p = True
if node is q: found_q = True
if node is p or node is q: return node
if left and right: return node
return left or right
lca = dfs(root)
return lca if found_p and found_q else None
function lowestCommonAncestor(root: TreeNode | null, p: TreeNode, q: TreeNode): TreeNode | null {
let foundP = false, foundQ = false;
const dfs = (node: TreeNode | null): TreeNode | null => {
if (!node) return null;
const left = dfs(node.left);
const right = dfs(node.right);
if (node === p) foundP = true;
if (node === q) foundQ = true;
if (node === p || node === q) return node;
if (left && right) return node;
return left ?? right;
};
const lca = dfs(root);
return foundP && foundQ ? lca : null;
}