给定一棵二叉树及其中两个节点 p、q,返回它们的最近公共祖先。一个节点可以是它自己的祖先。
当前节点是否为公共祖先,取决于 p、q 在左右子树中的查找结果,所以适合后序 DFS。
也就是说,要先问左右子树:“你们那里有没有找到 p 或 q?”拿到左右子树的答案后,当前节点才能判断自己是不是最近公共祖先。
递归函数的含义是:在以 root 为根的子树中寻找 p 和 q。
它可能返回三类结果:
null:这棵子树里没有找到 p 或 q。p 或 q:这棵子树里找到了其中一个目标节点。p 和 q,最近公共祖先已经确定。递归处理时分四种情况:
null。p 或 q,返回当前节点。以示例中的 p = 5、q = 1 为例:
为什么这里的 3 是“最近”的?
因为 p 和 q 是第一次在节点 3 这里从左右两侧汇合。再往上的节点虽然也是公共祖先,但离 p、q 更远,所以不是最近公共祖先。
若当前节点就是 p,直接返回 p。
这里不需要继续向下查找,是因为题目允许“一个节点是它自己的祖先”:
q 在 p 的子树中,答案就是 p。q 不在 p 的子树中,上层递归会把 p 和另一侧找到的 q 汇合,再确定答案。q 命中时同理。
O(n),最坏情况下需要访问每个节点一次。O(h),h 为树高,主要来自递归调用栈。最坏情况下树退化成链表,空间复杂度为 O(n);平衡二叉树中为 O(log n)。p、q 都在树中;若不保证,需额外记录找到的目标数量。root === p,不能只比较值,节点值可能重复。p 或 q 后返回节点值,应返回节点本身。