6

二叉树两个节点的最近公共祖先问题 - Grey Zeng

 1 year ago
source link: https://www.cnblogs.com/greyzeng/p/16757504.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

二叉树两个节点的最近公共祖先问题

作者:Grey

原文地址:

博客园:二叉树两个节点的最近公共祖先问题

CSDN:二叉树两个节点的最近公共祖先问题

题目描述#

给定一棵二叉树的头节点 head,和另外两个节点 a 和 b , 返回 a 和 b 的最低公共祖先。

题目链接见:LeetCode 236. Lowest Common Ancestor of a Binary Tree

主要思路:

本题也是利用二叉树的递归套路来解。

定义好 Info 信息

    public static class Info {
        public Info(boolean findA, boolean findB, TreeNode ancestor) {
            this.findA = findA;
            this.findB = findB;
            this.ancestor = ancestor;
        }
        private boolean findA;
        private boolean findB;
        private TreeNode ancestor;

    }

findA表示能否在当前(子)树下找到 a 节点;

findB表示能否在当前(子)树下找到 b 节点;

ancestor表示当前两个节点的最低公共祖先是什么。

首先考虑一些边界条件,例如

if (a == null) {
    // a 为 null,不管 b 是否为 null,公共祖先都是 b
    return b;
}
if (b == null) {
    // b 为 null, 不管 a 是否为 null,公共祖先都是 a
    return a;
}

定义递归函数

Info p(TreeNode head, TreeNode a, TreeNode b)

递归含义是:以 head 为头的树,a 和 b 的公共祖先是什么,封装成 Info 返回。

接下来看递归函数的主要逻辑

首先是 base case,如果 head 为 null,则 findA = false,findB = false,a 和 b 的公共祖先也是 null

        if (head == null) {
            return new Info(false, false, null);
        }

分析了 base case,接下来是普遍情况,如果 head 不为 null,则去左树收集信息,去右树也收集信息,然后把左右两树的信息整合成 head 的信息返回

// 左树收集信息
Info leftInfo = p(head.left, a, b);
// 右树收集信息
Info rightInfo = p(head.right, a, b);

// 整合
......

最后,我们需要把左右两树返回的信息进行整合,首先,以 head 为头的树,findA的取值取决于如下三种情况:

情况1,左树包含 a,即 leftInfo.findA

情况2,右树包含 a,即 rightInfo.findA

情况3,head 就是 a

三个情况有一个满足,以 head 为头的树 findA = true,

findB类似,

即下述代码所表达的含义

//  这
boolean findA = leftInfo.findA || rightInfo.findA || head == a;
boolean findB = leftInfo.findB || rightInfo.findB || head == b;

接下来看两个节点的最低公共祖先,首先,如果左树上找到 a 和 b,那么 leftInfo.ancestor 就是 a 和 b 的最低公共祖先;

如果右树上找到 a 和 b,那么 rightInfo.ancestor 就是 a 和 b 的最低公共祖先;

如果左右树一边找到一个,则 head 就是 a 和 b 的最低公共祖先;

如果 a 和 b 在树上都找不到,即findA = false, findB = false,那么 a 和 b 的最低公共祖先就是 null。

即下述代码逻辑

        
        if (findA && findB) {
            if (leftInfo.findA && leftInfo.findB) {
                return new Info(true, true, leftInfo.ancestor);
            } else if (rightInfo.findA && rightInfo.findB) {
                return new Info(true, true, rightInfo.ancestor);
            }
            return new Info(true, true, head);
        }
        return new Info(findA, findB, null);

完整代码见

class Solution {
    public static TreeNode lowestCommonAncestor(TreeNode head, TreeNode a, TreeNode b) {
        if (a == null) {
            return b;
        }
        if (b == null) {
            return a;
        }
        // o1和o2都不为null
        return p(head, a, b).ancestor;
    }

    public static Info p(TreeNode head, TreeNode a, TreeNode b) {
        if (head == null) {
            return new Info(false, false, null);
        }
        Info leftInfo = p(head.left, a, b);
        Info rightInfo = p(head.right, a, b);
        boolean findA = leftInfo.findA || rightInfo.findA || head == a;
        boolean findB = leftInfo.findB || rightInfo.findB || head == b;
        if (findA && findB) {
            if (leftInfo.findA && leftInfo.findB) {
                return new Info(true, true, leftInfo.ancestor);
            } else if (rightInfo.findA && rightInfo.findB) {
                return new Info(true, true, rightInfo.ancestor);
            }
            return new Info(true, true, head);
        }
        return new Info(findA, findB, null);
    }

    public static class Info {
        public Info(boolean findA, boolean findB, TreeNode ancestor) {
            this.findA = findA;
            this.findB = findB;
            this.ancestor = ancestor;
        }

        private boolean findA;
        private boolean findB;
        private TreeNode ancestor;

    }
}

时间复杂度为O(N)(即一次后序遍历的时间复杂度)

更多#

算法和数据结构笔记


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK