1、题目描述
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。
2、算法分析
首先理解二叉树的遍历递归方法。这篇文章写的不错。
https://blog.csdn.net/allenchenhh133/article/details/80291252
总结下二叉树的递归:
① 从根节点往左子树或者是右子树继续遍历。
举例:
root.left遍历左子树,一直遍历到结点为空 或者停止的那个条件为止,左子树为空,右子树也为空,然后返回上一层。继续遍历当前结点的右子树,然后再继续遍历当前结点的左子树,直到左子树为空,遍历右子树,右子树也为空的话。返回上一层。知道返回到根节点。
root.right遍历右子树,一直遍历到右子树为空为止,然后遍历当前结点的左子树,左子树为空的话,返回上一层。依次遍历到root为止。
小结:先遍历到叶节点,然后不满足条件后,再往上推。
再看本题分析:
本题要求找到最近的祖先结点,有以下几种情况:
① 两个结点其中的一个结点值和root根节点值相等
② 一个结点也可以是自己的祖先
③ 两个结点分布在root根节点的两侧,左子树和右子树,那么最近祖先就是根节点
④ 若所寻找的结点在根节点的一侧,左子树和右子树的其中一边, 那么返回的是相对的结点的值(具体看代码)
3、代码实现
/**
* 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){
return null;
}
// 如果根节点的值 等于 p 或者是q 节点的值,那么节点的值是自己的祖先
// 比如查找3,4结点,3正好为root结点值,所以返回的是根结点的值
if(root.val == p.val || root.val == q.val){
return root;
}
// 分别在左右子树寻找p,q的公共节点
TreeNode leftVal = lowestCommonAncestor(root.left,p,q);
TreeNode rightVal = lowestCommonAncestor(root.right,p,q);
// 如果左右结点都不为空,那么分别分布在根节点的两侧,那么返回的是root结点
if(leftVal != null && rightVal != null){
return root;
}
// 如果左子树没找到,那么返回右子树查找的值
if(leftVal == null){
return rightVal;
}
// 如果右子树没找到,那么返回左子树查找的值
if(rightVal == null){
return leftVal;
}
// 如果都没找到则返回null
return null;
}
}