剑指 Offer 68 - II. 二叉树的最近公共祖先
难度简单253
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
示例 1:
1 | 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 |
示例 2:
1 | 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 |
说明:
- 所有节点的值都是唯一的。
- p、q 为不同节点且均存在于给定的二叉树中。
注意:本题与主站 236 题相同:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/
优雅写法
如果当前的根节点为空,那么返回空
如果根节点不为空,
- 如果当前的根是
p
或者是q
,那么返回当前的根节点 - 如果当前的根既不是p也不是q,那么分别获取左子树中的返回值和右子树中的返回值
- 如果左子树中的返回值为空,那么说明两个节点都在右子树中,返回右子树的返回值
- 如果右子树中的返回值为空,那么说明两个节点都在左子树中,返回左子树的返回值
- 如果左右子树的返回值都不为空,那么说明两个节点分别在当前根节点的左右子树中,此时当前的根节点就是两个子节点的最近公共祖先返回当前的根节点。
- 如果当前的根是
1 | /** |
首先得到一条从根结点到树中某一结点的路径,这就要求在遍历的时候,有一个辅助内存来保存路径。比如我们用前序遍历的方法来得到从根结点到H的路径的过程是这样的:(1)遍历到A,把A存放到路径中去,路径中只有一个结点A;(2)遍历到B,把B存到路径中去,此时路径为 A->B;(3)遍历到 D,把D 存放到路径中去,此时路径为A->B->D;(4)遍历到F,把F存放到路径中去,此时路径为A->B->D->F;(5)F已经没有子结点了,因此这条路径不可能到达结点H。把F从路径中删除,变成A->B->D;(6)遍历G。和结点F一样,这条路径也不能到达H。遍历完G之后,路径仍然是A->B->D;(7)由于D的所有子结点都遍历过了,不可能到达结点H,因此D不在从A到H的路径中,把D从路径中删除,变成 A->B;(8)遍历 E,把 E 加入到路径中,此时路径变成A->B->E,(9)遍历H,已经到达目标结点,A->B->E就是从根结点开始到达H必须经过的路径。
同样,我们也可以得到从根结点开始到达 F 必须经过的路径是 A->B->D。接着,我们求出这两个路径的最后公共结点,也就是 B。B这个结点也是F和H的最低公共祖先。
1 | /** |
1 |
|
1 | class Solution { |