236. Lowest Common Ancestor of a Binary Tree

本文探讨了在二叉树中寻找两个指定节点的最低公共祖先(LCA)问题。介绍了两种解决方案,一种采用递归方式,另一种则使用迭代法,并详细解析了这两种方法的实现思路与步骤。

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

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”

        _______3______
       /              \
    ___5__          ___1__
   /      \        /      \
   6      _2       0       8
         /  \
         7   4

For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

s思路:
1. LCA. 还是树,树的问题就是如何遍历了。注意是binay tree,不是bst
2. 先来recursive,分别往底层找这两个指针,如果当前层的根指针root等于p或q,则返回p或q,这是recursive的边界情况,也就是元问题,到达元问题后,又逐级回到上层,先左边,后右边,如果左右都有返回,说明在这一级就是LCA,如果只有左边返回了指针,说明左边有一个指针,那就继续把左边的指针往上送,同理,只有右边返回指针,表明右边找到了一个指针,则把右边指针继续往上层送,等回到顶层的时候,就得到最后的LCA。整个过程是pre-order,因为先看当前root是否等于p或q,不等才左右搜索。
3. 搞清楚是pre-order,也就容易用iterative了。调试的时候,发现还不是简单的pre-order,不能按套路来,需要有新的想法。
4. 参考了答案。用的是queue来记录两个节点到root的path,把从child到parent的映射放在map里,然后等两个节点都找到,就把p->root这条path存在unordered_set,然后去查询q是否在这条path上,如果没有,就继续让q回到parent节点,知道找到为止,此时找到的就是LCA.
5. 思考什么时候用queue,什么时候用stack?

//方法1:
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        //
        if(!root||root==p||root==q) return root;
        TreeNode* l=lowestCommonAncestor(root->left,p,q);
        TreeNode* r=lowestCommonAncestor(root->right,p,q);        
        if(l&&r) return root;
        return l?l:r;
    }
};

//方法2:用的改造了的iterative.需要分清什么时候用queue,什么时候用stack!
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        //
        if(!root) return NULL;
        queue<TreeNode*> qq;//iterative不是都要用stack.这道题用stack就搞不定,需要其他辅助
        unordered_map<TreeNode*,TreeNode*> mm;//记录child->parent关系
        mm[root]=NULL;
        qq.push(root);
        while(!mm.count(p)||!mm.count(q)){
            TreeNode* cur=qq.front();
            qq.pop();
            if(cur&&cur->left){
                qq.push(cur->left);          
                mm[cur->left]=cur;
            }
            if(cur&&cur->right){
                qq.push(cur->right);
                mm[cur->right]=cur;
            }
        }

        unordered_set<TreeNode*> ss;

        while(p){
            ss.insert(p);
            p=mm[p];
        }
        while(ss.count(q)==0){
            q=mm[q];
        }
        return q;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值