关于最近公共父节点问题,目前我遇到的有两类:
1、一类是给你一颗普通二叉树,让你求,你只能按部就班的求。
2、一类是给你一颗有一定条件约束的二叉树,让你求,这时候你就可以想办法利用这些设定约束条件。
例题一:给你一颗二叉搜索树,让你求两个节点的最近公共父节点。
分析:给定两个节点p,q。那么这两个节点相对于当前节点root来说,无外乎三种情况:
1)在root的左子树上
2)在root的右子树上
3)一个在左子树一个在右子树。
对于第三种情况,它的最近公共父节点就是root。对于前两种情况,那就递归继续往下找。
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null)
return null;
if (root.val > p.val && root.val > q.val)
return lowestCommonAncestor(root.left, p, q);
if (root.val < p.val && root.val < q.val)
return lowestCommonAncestor(root.right, p, q);
return root;
}
当然,如果你想不到利用这个条件,那你可以直接把二叉搜索树看作普通二叉树,用最一般的方法写也可,所以我们重点看下面普通二叉树如何求最近公共父节点。
例题二、给你一颗二叉树,让你求p,q的最近公共父节点。
思考:二叉树题,大概率躲不开二叉树的三种深度遍历以及层次遍历。当从root开始往下递归到某一层节点root1时,现在该如何分析呢??很明显,如果root1是p节点或者是q节点,那就说明找到了一个子节点,将root1返回到上一层,一直返回到它的父节点。如果不是,那就将root1.left节点放入递归函数,root.right节点放入递归函数,可以得到root.left和root.right所得返回值。此时两个返回值会出现四种情况:
1)如果此时两个返回值都不为空,说明root1.left进入递归后找到了p,q其中的一个。root1.right也找到了其中另一个,那么root1就是要找的公共父节点啊。
2)如果root1.left返回值为空,就说明左侧没找到,那就是都在root1.right节点下,因此返回root.right。
3)如果root1.right为空,那就返回root.left。
4)如果都为空,那就说明没找到,返回空。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null){
return null;
}
if(root == p || root == q){
return root;
}
TreeNode l = lowestCommonAncestor(root.left, p, q);
TreeNode r = lowestCommonAncestor(root.right, p, q);
if(l != null && r != null){
return root;
}
if(l != null && r == null){
return l;
}
if(l == null && r != null){
return r;
}
return null;
}
}