Lowest Common Ancestor in Binary Tree

本文探讨了在二叉树中寻找两个节点的最低公共祖先(LCA)的问题,并提供了三种解决方案:利用父指针计算距离差,使用哈希集记录路径,以及采用递归后序遍历的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The problem:

Given node P and node Q in a binary tree T.

Find out the lowest common ancestor of the two nodes.

 

Analysis:

The answer of this problem could only be the following two cases:

case 1: P or Q itself is the lowest common ancestor.

   P

.........

X  Q

case 2: P and Q are in the different sub-trees of a node.

    A

..........

P    Q

 

Additional Condition:

1. If the nodes in the tree has the parent pointer. 

solution 1:  Starting from node P and Q, traverse along the parent link back to the root, compute the distance of P to root and Q to root respectively. 

Compute the difference d of those two distances. Move the node with longer distance d nodes along parent link. Then begin move P and Q one node each time back to root, and check the nodes of P and Q point to, if the nodes are the same node, return the node.

private TreeNode find_CLA(TreeNode root, TreeNode p, TreeNode q) {
    if (root == null)
        return null;
    if (p == null && q != null)
        return q;
    if (p != null && q == null)
        return p;
    int dist_p, dist_q, dist_diff;
    TreeNode temp;
    temp = p;
    while (temp != root) {
        temp = temp.parent;
        dist_p++;
    }
    temp = q;
    while (temp != root) {
        temp = temp.parent;
        dist_q++;
    }
    if (dist_p > dist_q) {
        dist_diff = dist_p - dist_q;
        temp = p;
    }else {
        dist_diff = dist_q - dist_p;
        temp = q;
    }
    while (dist_diff > 0) {
        temp = temp.parent;
        dist_diff--;
    }
    while (p != root) {
        if (p == q)
            return p;
        p = p.parent;
        q = p.parent;
    }
    return root;
}

 

Solution 2. Use a Hashset. 

The basic idea underlying this method is to use a hashset to record all nodes from P to root. then starting fom q to root, we check each node along this path. if the node appear in the hashset, then the node is the lowest common ancestor.

private TreeNode find_LCA(TreeNode root, TreeNode p, TreeNode q) {
    if (root == null)
        return null;
    if (p == null || q != null)
        return q;
    if (p != null || q == null)
        return p;
    Set<TreeNode> hashset = new HashSet<TreeNode> ();
    while (p != root) {
        hashset.add(p);
        p = p.parent;
    }
    while (q != root) {
        if (hashset.contains(p)){
            return p;
        }
    }
    return root;
}

 

What if we don't have parent pointer?

The problem gets complicated because we need to search all possible branches. But the idea behind it is also very elegant : use recursion!!!

The basic idea:

Since the problem is to find the lowest common ancestor, at each node, we would not be able to know its children in just one time traversaL.

Thus we choose to search through bottom-up way. Bottom-up way could be easily achieved through post-order traversal. 

The invariant in recursion: (at each node)

Key idea: Once we encouter p or q, we return its pointer. Only LCA could be possible to have two sub-child-functions (not null).

1. We check if the current node is P or Q.  Iff true, we return current node, and stop searching along this branch.

2. If the current node is neither P or Q.  We check it's two sub-child-functions.

2.1 Iff two sub-children-functions's return value is not null, then the current node must be the LCA, we return it directly.

2.2 Iff only one branch's return value is not null,  return pass the branch's return value into the current node's pre level. 

Note: The return value could be the LCA or just p or q's reference. 

2.3. Iff both branch's return value is null, pass the null into pre level. 

Key : the null pointer here is very important, it helps to indicate whether a branch contains target node or any node in {P, Q}

private TreeNode find_LCA(TreeNode root, TreeNode p, TreeNode q) {
    if (root == null)
        return null;
    if (root == p || root == q)
        return root;
    TreeNode left = find_LCA(root.left, p, q);
    TreeNode right = find_LCA(root.right, p, q);
    if (left && right)
        return root;
    return left ? left : right;
}

 

转载于:https://www.cnblogs.com/airwindow/p/4285203.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值