二叉树的最近公共祖先

二叉树的最近公共祖先


问题

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。也是leetcode的236题。公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。

解决方法

1.简单版

代码如下:

    public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {
        HashMap<TreeNode, TreeNode> fatherMap = new HashMap<>();
        fatherMap.put(root, root);
        process(root, fatherMap);
        HashSet<TreeNode> set = new HashSet<>();
        TreeNode cur = p;
        while (cur != fatherMap.get(cur)) {
            set.add(cur);
            cur = fatherMap.get(cur);
        }
        set.add(root);

        while (!set.contains(q)) {
            q = fatherMap.get(q);
        }
        return q;

    }
    private void process(TreeNode root, HashMap<TreeNode, TreeNode> fatherMap) {
        if (root == null)
            return;

        fatherMap.put(root.left, root);
        fatherMap.put(root.right, root);

        process(root.left, fatherMap);
        process(root.right, fatherMap);

    }

也就是定义一个HashMap,直接把每个节点的父亲给存进去,头结点root的父亲是它本身。存完之手,得到一个FatherMap,里面有每个节点的父亲,此时我们可以再定义一个Set集合,把p节点以及p节点的所有祖先节点都存进去,然后再去找q节点以及q的祖先,看其是否在Set集合内,找到的第一个节点就是他们的最近公共祖先。

2.优化版

代码如下:

    public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode p, TreeNode q) {
        //如果节点为空了,或者节点等于p或者q就返回该节点
        //第一个root ==null 是判断到了最后节点。
        //root == p 或者 root == q 则是情况1,
        // 也就是当找到第一个p或者q的时候,他就可能是LCA,就返回自己
        if (root == null || root == p || root == q)
            return root;

        TreeNode left = lowestCommonAncestor2(root.left, p, q);
        TreeNode right = lowestCommonAncestor2(root.right, p, q);

        //如果左孩子不等于null且右孩子也不等于null,则表示,
        // p跟q就在他们的左右孩子里,那么这个root就是他们的LCA
        if (left != null && right != null)
            return root;

        //这里会返回有p或者q的节点
        return left != null ? left : right;
    }

这里思考一下,二叉树最低公共子先问题,它只有两种情况,
1、p是q的LCA,或者q是p的LCA。
2、p 跟 q都不互为LCA,需要往上找才知道他们的LCA
每次只返回p或者q,如果该子树上不含p或q则返回null,然后在每个节点处都要进行判断,如果该节点的左右孩子都不为null,也就意味着他的左右孩子含有p和q才会不为null,这是这个节点就肯定是他们的祖先节点。如果该节点的左右孩子有为null的情况,则返回有p或者q的,也就是不为null的节点,或者返回null。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值