剑指offer-树中两个节点的最低公共祖先

对于这个问题不同的条件可以有不同的解法

  • 树是二叉树且是二叉搜索树。

    这里写图片描述

BinaryTreeNode *GetLastCommonParent(BinaryTreeNode *pRoot,BinaryTreeNode *pNode1,BinaryTreeNode *pNode2)
{
    if (NULL == pRoot)
        return NULL;
    if (pRoot->_data > pNode1->_data && pRoot->_data > pNode2->_data) //当前结点的值比两个节点的值都大公共祖先一定在左子树中
        return GetLastCommonParent(pRoot->_pLeft, pNode1, pNode2);
    else if (pRoot->_data < pNode1->_data && pRoot->_data < pNode2->_data)//前结点的值比两个节点的值都小公共祖先一定在右子树中
        return GetLastCommonParent(pRoot->_pRight, pNode1, pNode2);
    else //
        return pRoot;
}
  • 树中的每个结点都有指向父结点的指针
    这里写图片描述
    这样就转换成了求两个链表的第一个公共结点。

  • 普通二叉树(没有父结点指针)
    这里写图片描述
    这里写图片描述
    实现代码

//普通二叉树,没有parent指针
 //非递归的解法
//1.获取结点所在的路径,将路径保存在链表里
bool GetNodePath(BinaryTreeNode *pRoot, BinaryTreeNode *pNode, list<BinaryTreeNode*>&path)
{
    if (NULL == pRoot || NULL == pNode)
        return false;
    if (pRoot == pNode)
        return true;
    path.push_back(pRoot);
    bool found = false;
    found = GetNodePath(pRoot->_pLeft, pNode, path);
    if (!found)
        found = GetNodePath(pRoot->_pRight, pNode, path);
    if (!found)
        path.pop_back();
    return found;
}
//2. 寻找两个链表的公共节点
BinaryTreeNode *GetCommNode(const list<BinaryTreeNode *>&path1,const list<BinaryTreeNode *> &path2)
{
    list<BinaryTreeNode *>::const_iterator iter1 = path1.begin();
    list<BinaryTreeNode *>::const_iterator iter2 = path2.begin();
    BinaryTreeNode *pNode = NULL;
    while (iter1 != path1.end() && iter2 != path2.end())
    {
        if (*iter1 == *iter2)
            pNode = *iter1;
        iter1++;
        iter2++;
    }
    return pNode;
}
BinaryTreeNode *GetCommParent(BinaryTreeNode *pRoot, BinaryTreeNode * pNode1, BinaryTreeNode *pNode2)
{
    if (NULL == pRoot || NULL == pNode1 || NULL == pNode2)
        return NULL;
    list<BinaryTreeNode *> path1;
    list<BinaryTreeNode *> path2;
    BinaryTreeNode *Parent = NULL;
    bool ret1 = GetNodePath(pRoot, pNode1, path1); 
    bool ret2 = GetNodePath(pRoot, pNode2, path2);
    if (ret1 && ret2)
    {
        Parent = GetCommNode(path1, path2);
    }
    return Parent;
}

这里写图片描述
非递归解法:
这里写图片描述

//递归解法
bool FindNode(BinaryTreeNode *pRoot, BinaryTreeNode *pNode)
{
    if (NULL == pRoot)//上层调用函数已经进行了判空
        return false;
    if (pRoot == pNode)
        return true;
    bool found = false;
    found = FindNode(pRoot->_pLeft, pNode);
    if (!found)
        found = FindNode(pRoot->_pRight, pNode);
    return found;
}
BinaryTreeNode *GetCommonParent1(BinaryTreeNode *pRoot,BinaryTreeNode *pNode1,BinaryTreeNode *pNode2)
{
    if (NULL == pRoot || NULL == pNode1 || NULL == pNode2)
        return NULL;
    if (FindNode(pRoot, pNode1) && FindNode(pRoot, pNode2))
    {
        if (FindNode(pRoot->_pLeft, pNode1) && FindNode(pRoot->_pLeft, pNode2))
            return GetCommonParent1(pRoot->_pLeft, pNode1, pNode2);
        else if (FindNode(pRoot->_pRight, pNode1) && FindNode(pRoot->_pRight, pNode2))
            return GetCommonParent1(pRoot->_pRight, pNode1, pNode2);
        else 
            return pRoot;
    }
    return NULL;
}

思路参考自剑指offer,解析摘自剑指offer.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值