LeetCode100之二叉树的最近公共祖先(236)--Java

1.问题描述

        给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

        示例1

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点5和节点1的最近公共祖先是节点3 。

        示例2 

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点5和节点4的最近公共祖先是节点5。
因为根据定义最近公共祖先节点可以为节点本身

        示例3 

输入:root = [1,2], p = 1, q = 2
输出:1

        提示

  • 树中节点数目在范围 [2, 105] 内。
  • -109 <= Node.val <= 109
  • 所有 Node.val 互不相同 。
  • p != q
  • p 和 q 均存在于给定的二叉树中。

        难度等级

                中等

        题目链接

                二叉树的最近公共祖先

2.解题思路

        这道二叉树的最近公共祖先问题,说通俗点,就是找到一个共同的根节点或者是它们根节点的共同根节点。这里的第一步是找到p和q这两个节点,然后才来找共同的祖先,所以我们用到遍历方式是后序遍历。

        首先,第一步是确定递归的结束条件,如果根节点为空,或者根节点就是p、q,那我们直接将节点返回即可。

        //如果节点为空或者p、q其中一个,直接返回
        if(root == null || root == p || root == q){
            return root;
        }

        接着,我们就要来处理单层的递归逻辑。后序遍历的顺序是左右根,所以我们要分别调用递归方法获取当前根节点的左右节点的情况,从左右节点中看看能不能找到它们本身或者它们的祖先。

        //左
        TreeNode left = lowestCommonAncestor(root.left,p,q);
        //右
        TreeNode right = lowestCommonAncestor(root.right,p,q);

        然后,根据左右节点的情况进行当前节点的处理。

        情况一:如果左右节点都不为空,那说明左右节点可以找到p和q,所以根节点是它们的共同祖先,将根节点返回。

        //根
        //如果左右节点不为空,返回当前节点
        if(left != null && right != null){
            return root;
        }

        情况二:左右两个节点其中一个为空,另外一个不为空,那么不为空的那个节点,可以顺着下去找到p或者q或者pq的共同祖先,所以这时候,我们将不为空的那个节点返回即可。

        //如果其中一个节点不为空,返回不为空的节点
        if(left != null || right != null){
            return left != null ? left : right;
        }

        情况三:左右两个节点都是空,直接返回空就好了。

        //如果不是以上情况,返回空节点
        return null;

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) {
        //如果节点为空或者p、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 root;
        }
        //如果其中一个节点不为空,返回不为空的节点
        if(left != null || right != null){
            return left != null ? left : right;
        }
        //如果不是以上情况,返回空节点
        return null;

    }
}

4.总结

        这道题就是简单的考察了一下后序遍历和对最近共同祖先的理解,不是很难。这道题我就不啰嗦太多了,祝大家刷题愉快~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiao--xin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值