树---求给定二叉树中两节点的最低公共祖先(LCA)

一、问题描述

对于一颗二叉树,给定其中的两节点n1,n2,求出他们的最低公共祖先(Lowest Common Ancestor )。例如:
这里写图片描述

二、问题求解

利用递归思想。

1)从root开始遍历,如果n1和n2中的任一个和root匹配,那么root就是LCA。
(2) 如果都不匹配,则分别递归左、右子树,如果有一个 key(n1或n2)出现在左子树,并
且另一个key(n1或n2)出现在右子树,则root就是LCA.  
(3)如果两个key都出现在左子树,则说明LCA在左子树中,否则在右子树。

三、实现代码

时间复杂度为O(n)

#include<iostream>
using namespace std;

typedef int KeyType;
typedef struct BinaryTreeNode
{
    KeyType key;
    struct BinaryTreeNode *left;
    struct BinaryTreeNode *right;
}BTNode, *BiTree;
//创建二叉树节点
BTNode *CreateBTNode(KeyType key)
{
    BTNode *node = new BTNode;
    node->key = key;
    node->left = node->right = NULL;
    return node;
}
//对于给定的树中两节点n1和n2,返回两者lca的指针
BTNode *findLCA(BTNode *root, KeyType n1, KeyType n2)
{
    if(root == NULL) return NULL;

    //(1)n1,n2中的一个是另一个的父节点,即为LCA
    if(root->key==n1 || root->key==n2)
        return root;
    //(2)n1,n2没有父子关系,这时又存在两种情况:
    //case1:同在一个子树。case2:分别在两个子树。
    BTNode *left_lca=findLCA(root->left, n1, n2);
    BTNode *right_lca=findLCA(root->right, n1, n2);
    //都为真,说明两边子树都能找到n1或n2,这是case2的情况
    if(left_lca && right_lca)
        return root;//当n1,n2分别在两个子树时lca即为根节点
    //case1的情况
    return (left_lca != NULL)?left_lca:right_lca;
}

int main()
{
    BTNode *root = CreateBTNode(1);
    root->left = CreateBTNode(2);
    root->right = CreateBTNode(3);
    root->left->left = CreateBTNode(4);
    root->left->right = CreateBTNode(5);
    root->right->left = CreateBTNode(6);
    root->right->right = CreateBTNode(7);

    cout <<"LCA(4, 5): "<<findLCA(root, 4, 5)->key<<endl;
    cout <<"LCA(4, 6): "<<findLCA(root, 4, 6)->key<<endl;
    cout <<"LCA(3, 4): "<<findLCA(root, 3, 4)->key<<endl;
    cout <<"LCA(2, 4): "<<findLCA(root, 2, 4)->key<<endl;
    return 0;
}

结果:

LCA(4, 5): 2
LCA(4, 6): 1
LCA(3, 4): 1
LCA(2, 4): 2

Process returned 0 (0x0)   execution time : 0.279 s
Press any key to continue.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值