lca是深度最大的同时为两节点祖先的节点;递归解法通过后序遍历,以返回值传递子树是否含p/q或已找到lca的信息,核心是左右非空则当前节点为lca。
什么是LCA?先看最核心的判断逻辑
二叉树中两个节点的最近公共祖先(LCA),是指**深度最大的、同时是这两个节点祖先的节点**。关键不在于“怎么找”,而在于如何定义“祖先”和“最近”——它必须满足:从根出发,root能同时到达 p 和 q,且左右子树分别包含其中一个(或自身就是 p 或 q)。
递归解法:用返回值传递存在性信息
标准做法是后序遍历,每个节点返回:nullptr(子树里没 p 也没 q)、p、q 或 LCA 节点本身。核心逻辑在回溯时判断:
- 如果左子树返回非空,右子树也返回非空 → 当前
root就是 LCA - 如果只有一边非空 → 直接返回该非空指针(表示这一侧已找到目标,或已找到 LCA)
- 注意:一旦
root == p或root == q,立即返回root,不继续向下——这是保证“最近”的关键
示例片段(省略 TreeNode 定义):
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root || root == p || root == q) return root;
auto left = lowestCommonAncestor(root->left, p, q);
auto right = lowestCommonAncestor(root->right, p, q);
if (left && right) return root;
return left ? left : right;
}
为什么不能用父指针或存储路径?常见误区
虽然用哈希表存每个节点的父节点再向上追溯也能做,但问题在于: