236. 二叉树的最近公共祖先
解题思路
祖先的定义: 若节点 p p p 在节点 r o o t root root 的左(右)子树中,或 p = r o o t p = root p=root,则称 r o o t root root 是 p p p 的祖先。
最近公共祖先的定义: 设节点 r o o t root root 为 节点 p 、 q p、q p、q 的某公共祖先,若其左子节点 r o o t . l e f t root.left root.left 和 右子节点 r o o t . r i g h t root.right root.right 都不是 p 、 q p、q p、q 的公共祖先,则称 r o o t root root 是 “最近的公共祖先”。
根据以上定义,若 r o o t root root 是 p 、 q p、q p、q 的最近公共祖先,则只可能为以下情况之一:
- p p p 和 q q q 在 r o o t root root 的子树中,且分列 r o o t root root 的异侧(即分别在左、右子树中);
- p = r o o t p = root p=root,且 q q q 在 r o o t root root 的左或右子树中;
- q = r o o t q = root q=root,且 p p p 在 r o o t root root 的左或右子树中;
考虑通过递归对二叉树进行后序遍历,当遇到节点 p
或 q
时返回。从底至顶回溯,当节点 p、q
在节点 root
的异侧时,节点 root
即为最近公共祖先,则向上返回 root
。
递归解析
- 终止条件
- 当越过叶节点,则直接返回 n u l l null null;
- 当 r o o t root root 等于 p 、 q p、q p、q,则直接返回 r o o t root root;
- 递归工作
- 开启递归左子节点,返回值记为 l e f t left left;
- 开启递归右子节点,返回值记为 r i g h t right right;
- 返回值:根据 l e f t left left 和 r i g h t right right,可展开为四种情况:
- 当 l e f t left left 和 r i g h t right right 同时为空:说明 r o o t root root 的左/右子树都不包含 q 、 p q、p q、p,返回 n u l l null null;
- 当 l e f t left left 和 r i g h t right right 同时不为空:说明 p 、 q p、q p、q分列在 r o o t root root的异侧(分别在左/右子树),因此 r o o t root root为最近公共祖先,返回 r o o t root root。
- 当
l
e
f
t
left
left为空,
r
i
g
h
t
right
right不为空:
p
、
q
p、q
p、q 都不在
r
o
o
t
root
root的左子树中,直接返回
r
o
o
t
root
root。具体可以分为两种情况:
- (1) p 、 q p、q p、q 其中一个在 r o o t root root的右子树中,此时 r i g h t right right 指向 p (假设为 p p p)
- (2) p 、 q p、q p、q 两节点都在 r o o t root root的右子树中,此时的 r i g h t right right 指向 最近公共祖先节点
- 当 l e f t left left 不为空, r i g h t right right 为空:于情况 3 同理。
观察发现,情况1 可合并至 3 和 4 内。
参考代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
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) return right;
if(right == null) return left;
return root;
}
public TreeNode lowestCommonAncestor2(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 null; //1.
if(left == null) return right; // 3.
if(right == null) return left; // 4.
return root; //2. if(left != null && right != null)
}
}
部分图片来源于网络,版权归原作者,侵删。