题目描述
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”
_______3______
/ \
___5__ ___1__
/ \ / \
6 _2 0 8
/ \
7 4
For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
分析
传统的解法是:从根结点开始,分别记录从根结点到指定结点的路径path1和path2,再比较path1和path2最后一个相同的结点。
http://www.fusu.us/2013/06/p2-lowest-common-ancestor-in-binary-tree.html
这个网址给出了一个更简洁、高效的解法。主要思路是:
- 从叶结点开始,向上搜索
- 对于每一个结点node
- l:node的左子树是否出现过p或q
- r:node的右子树是否出现过p或q
- 如果l和r都不是null,则该结点即为lca
说明,对于一个结点node,l和r只可能有4种情况:
- l=null, r=null:node不含有p和q中的任意一个
- l!=null, r=null:node左子树含有其中一个
- l=null, r!=null:node右子树含有其中一个
- l!=null, r!=null:node左、右子树各有其中一个(由于是从叶节点向根结点搜索,所以最先出现该情况的结点,必为lca)
有没有可能,p是q的祖先?没有影响,因为如果是自身的话,也算包含在左右子树中。
-1
/ \
0 3
/ \
-2 4
/
8
具体分析:寻找结点值为8和4的lca
- 首先进入结点-1,0,-2
- 在结点-2时,-2的左结点是8,是其中一个结点,则l置为8,不为空。-2的右结点是null,r仍然是null。表面-2不是lca
- 进入结点0,此时l已经不是null,0的右结点是4,是其中一个结点,则r置为4,不为空。
- 此时,l和r都不为null,0就是lca
代码
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// 发现目标结点,则标记(left或right)
if (root == null || root == p || root == q)
return root;
// 查看左右子树是否有目标结点
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
// 左右子树同时含有目标结点,则该结点是lca
if (left != null && right != null)
return root;
// 左右子树只有一个含有目标结点,向上返回
return left == null ? right : left;
}