题目链接
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/
题意
中文题,就是给出一个一般的二叉树,求其最近公共祖先,并且声明节点A是本节点的祖先。
题解
算是“二叉搜索树的最近公共祖先”问题的升级版,但是仍然没有比较使用LCA算法。可以利用二叉树的性质,利用DFS的方法来求解。仍然分析公共祖先与根root的关系,总共有3种:
1.在root的左子树
2.在root的右子树
3.root本身
因为结点本身就是该结点的祖先,所以3的情况是存在的。那么我们可以先判定一下root本身:
if(root == null) return null;
if(root == p || root == q) return root;
如果是空,那就直接返回null,如果是搜索的一个结点,因为本身也是祖先,所以需要返回root。
那么在递归的时候,就能判定出两个结点分别的最近公共祖先。这样,如果我们回溯的时候返回null或者root,那么回溯的上一层,一定存在这样的四种情况:
1.没有递归,直接返回root。
2.left回溯回来了一个值,而right为null。
3.right回溯回来了一个值,而left为null。
4.left与right都回溯回来了一个值。
对于1,就没啥好说了,没有再搜索下去的必要,就算其子孙有一个为另一个结点,那该该节点就是正确答案。对于4,说明节点相对于root分散在两个子树,那么该结点就是答案了,因为是回溯,这个就是最近公共祖先。对于2、3实际上是一种类似的情况,root的一个子树上有需要找的结点,那么此时存在两种可能:
1.另一个结点也在该子树上
2.另一个结点在其他兄弟或者祖先的兄弟上
那么实际上解决方法都是向上回溯该结点,因为如果是情况1,这个结点就是答案了,如果是情况2,那么就继续向上回溯,直到碰见有一个结点满足情况4。
是有一点绕了,其实直接裸奔LCA应该也是没什么问题的。这样代码更简单一点。
Java 代码
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return null;
if(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 root;
return left == null ? right : left;
}
}