在二叉树中查找两个节点的最近的公共祖先节点(有回溯指针)(NCA--nearest common ancestor)

这个题目有两个变种:有回溯指针的二叉树和无回溯指针的二叉树

题目:
给出两个节点node1,node2和二叉树根节点root,查找node1和node2的最近的公共祖先节点;特殊值(简易)之处在于每个节点都有一个指向父节点的回溯指针

解法一:最常规的解法--依次轮询
思路:
使用回溯指针可以找到node1和node2到root的路径,在这两条路径上总有一个汇聚点,通过轮询可以找到

评价:
这是最通俗易懂的方法,但是效率很低o(n^2),n为树的高度

代码:
/*
寻找 两个节点的最近公共祖先节点 

*/
BitTree NCA(BitTree *root, BitTree *node1, BitTree *node2)
{
    if(!root) return null;
    BitTree *tmp;
    while(node1)
    {
        tmp = node2;
        while(tmp)
        {
            if(node1 == tmp) return node1;
            tmp = tmp->parent;
        }
        node1 = node1->parent();
    }
}




解法二:巧妙转化
思路:
第一种方式是倒序的,找到第一个相同的节点就是NCA;但是效率太差。
其实我们可以两次轮询后保存下node1和node2到root的路径,然后从头开始轮询两条路径,也可以很快找到,而且复杂度是o(3n),n是树的高度

评价:
巧妙的转化为了求两个线性表的第一个不同节点。

代码:
/*
获取两个节点的最近公共祖先节点 
*/
BitTree * NCA(BitTree *root, BitTree *node1, BitTree *node2)
{
        BitTree *tmp;
        int len1 = 0, len2 = 0;
        int path1[100] = {0}, path2[100] = {0};
        if(!root) return null;
        while(node1->parent)
        {
                    tmp = node1;
                    node1 = node1->parent;
                    if(node1->left == tmp){path1[len1++] = 1;}
                    else{path1[len1++] = 0;}
        }
        while(node2->parent)
        {
                    tmp = node2;
                    node2 = node2->parent;
                    if(node2->left == tmp){path2[len2++] = 1;}
                    else{path2[len2++] = 0;}
        }
        for(; len1 > 0 && len2 > 0;)
        {
                if(path1[--len1] != path2[--len2])
                {
                                 return root;
                }
                root = (path1[len1] == 1? root->left:root->right);
        }
}



解法二:哈希高效
思路:
哈希表的特性就是value可以直接定位到位置,而这里我们要做的无非就是看看两条路径的最近交叉点。所以可以先依次将node1到root的路径放入哈希表;然后轮询node2到root的路径,当第一次出现存在的key时则找到了NCA。

评价:
善于利用哈希表,尤其是当需要比较两个表中的元素异同的时候(之前的判断字母完全包含也是利用了这一点)

代码:

/*
对于hashtable的用法,不会,需要学习。
获取两个节点的最近公共祖先节点 
*/
BitTree * NCA(BitTree *root, BitTree *node1, BitTree *node2)
{
        if(!root) return null;
        hashTable<BitTree> h;
        while(node1)
        {
                    h.push(node1);
                    node1 = node1->parent();
        } 
        while(node2)
        {
                    if(h.exist(node2)) return node2;
                    node2 = node2->parent();
        }
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值