236. 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
思路
自底向上查找即可(回溯),后序遍历天然满足这个条件。接下来就看如何判断一个节点是节点q和节点p的公共祖先。
首先最容易想到的一个情况:如果找到一个节点,发现左子树出现结点 p,右子树出现节点 q,或者 左子树出现结点 q,右子树出现节点 p,那么该节点就是节点 p 和 q 的最近公共祖先。 即情况一:

判断逻辑是 如果递归遍历遇到 q,就将 q 返回,遇到 p 就将 p 返回,那么如果 左右子树的返回值都不为空,说明此时的中节点,一定是 q 和 p 的最近祖先。
接着是情况二,q 或者 p 为祖先节点:

1 | class Solution: |
注意,情况 2 在第一个 if 就判断了,例如对于例子中的 6,判断不为 q 或者 p,则访问其子节点,左边直接返回 q,右边返回 None,此时就直接返回 q 为最终结果了。因为在左边查找到了一个节点,右边为空,则说明两个节点一定在一个子树上,所以直接返回找到的 q。
235. 二叉搜索树的最近公共祖先
在上一题的基础上添加了限制为二叉搜索树。
思路
搜索二叉树是有序的,所以最近公共子节点一定在区间 [q, p] 或者 [p, q] 中。那么只要从上到下去遍历,遇到 cur节点是数值在[p, q]区间中则一定可以说明该节点cur就是p 和 q的公共祖先。 那问题来了,一定是最近公共祖先吗?
如图所示,首先遍历到 10,q p 都小于 10,则遍历左子树,第一次遇到 5,满足条件,p q 一定一个在左边一个在右边,如何再遍历,则后续节点都不是公共祖先了。

1 | class Solution: |