二叉树两结点的最低公共父结点

该博客讨论了如何在二叉树中找到任意两个节点的最低公共父节点。通过从根节点开始遍历,判断当前节点的左右子树是否包含目标节点来确定最低公共父节点。当两个节点分别位于左、右子树时,当前节点即为答案。文章也提及了时间复杂度问题,并提到如果节点包含指向父节点的指针,问题可以转换为链表问题来解决。

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

题目:求二叉树中任意两个节点的最低公共父节点。

思路:
从根结点开始遍历,判断以当前结点为根的树中左右子树是不是包含我们要找的两个结点。如果两个结点都出现在它的左子树中,那最低的共同父结点必出现在它的左子树中;如果两个结点都出现在它的右子树中,那最低的共同父结点也出现在它的右子树中;如果两个结点一个出现在左子树中,一个出现在右子树中,那当前的结点就是最低的共同父结点。

struct BinaryTreeNode {
    int value;
    BinaryTreeNode *left;
    BinaryTreeNode *right;
}

bool containsNode(BinaryTreeNode *root,BinaryTreeNode *node){
    if(root == node)
        return true;
    bool flag = false;
    if(!flag && root->left != NULL)
        flag = containsNode(root->left,node);
    if(!flag && root->right != NULL)
        flag = containsNode(root->right,node);
    return flag;

}

BinaryTreeNode *lastCommonParentNode(BinaryTreeNode *root,BinaryTreeNode *node1,BinaryTreeNode *node2){
    if(root == NULL || node1 == NULL || node2 == NULL){
        return NULL;
    }
    bool leftsubtreehasnode1 = false;
    bool leftsubtreethasnode2 = false;
    if(root->left != NULL){
        leftsubtreehasnode1 = containsNode(root->left,node1);
        leftsubtreehasnode2 = containsNode(root->left,node2);
    }
    if(leftsubtreehasnode1 && leftsubtreehasnode2){
        if(root->left == node1 || root->left == node2)
            return root;
        return lastCommonParentNode(root->left,node1,node2);
    }

    bool rightsubtreehasnode1 = false;
    bool rightsubtreehasnode2 = false;
    if(root->right != NULL){
        if(leftsubtreehasnode1){
            rightsubtreehasnode1 = containsNode(root->right,node1);
        }
        if(leftsubtreehasnode2){
            rightsubtreehasnode2 = containsNode(root->right,node2);
        }   
    }
    if(rightsubtreehasnode1 && rightsubtreehasnode2){
        if(root->right == node1 || root->right == node2)
            return root;
        return lastCommonParentNode(root->right,node1,node2);
    }
    if((leftsubtreehasnode1 && rightsubtreehasnode2)|| (leftsubtreethasnode2 && rightsubtreehasnode1)){
        return root;
    }
    return NULL;    
}

时间复杂度为O(n^2),因为要遍历树中节点两遍,这显然不是最优的。

此题的变种:若每个节点都存有指向父节点的指针,如何求二叉树中任意两节点的最低公共子节点。

思路:此时我们可以把问题转化为两个单链表求第一个公共子节点。
这里写图片描述

而对于求两个单链表的第一个公共子节点则是我们比较熟悉的。

struct BinaryTreeNode {
    int value;
    BinaryTreeNode *left;
    BinaryTreeNode *right;
}

bool getNodePath(BinaryTreeNode *root,BinaryTreeNode *node,list<BinaryTreeNode*> &path){
    if(root == node)
        return true;
    path.push_back(root);
    bool found = false;
    if(root->left != NULL)
        found = getNodePath(root->left,node,path);
    if(!found && root->left != NULL)
        found = getNodePath(root->right,node,path);
    if(!found)
        path.pop_back();
    return found;       
}

BinaryTreeNode *LastCommonNode(const list<BinaryTreeNode*> &list1,const list<BinaryTreeNode*> &list2){
    list<BinaryTreeNode*> list1;
    list<BinaryTreeNode*> list2;

    list<BinaryTreeNode*>::const_iterator iter1 = list1.begin();
    list<BinaryTreeNode*>::const_iterator iter2 = list2.begin();
    BinaryTreeNode *lastcommonnode = NULL;
    while(iter1 != list1.end() && iter2 != list2.end()){
        if(*iter1 == *iter2)
            lastcommonnode = iter1;
        iter1++;
        iter2++;
    }
    return lastcommonnode;
}

BinaryTreeNode *getLastCommonNode(BinaryTreeNode *root,BinaryTreeNode *node1,BinaryTreeNode *node2){
    if(root == NULL || node1 == NULL || node2 == NULL)
        return NULL;
    list<BinaryTreeNode*> path1;
    getNodePath(root,node1,path1);

    list<BinaryTreeNode*> path2;
    getNodePath(root,node2,path2);

    return LastCommonNode(path1,path2);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值