码迷,mamicode.com
首页 > 编程语言 > 详细

2015-阿里C++研发附加题第一题

时间:2015-09-03 00:35:02      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:

技术分享

 

类似笛卡尔树的实现:

http://baike.baidu.com/link?url=nDGlKta6rvBzJ4_xm1TSp-Px05bU6gzgqWx7LnWwnXm5brtOCPJXXXRXeq9ZpIvsfrWkhua4D76oWrt2iQq2WK

 

从题目可以看出,按 a 来看的话,是一个二叉排序树,按 b 来看的话,是一个大根堆.

然后需要知道一个性质:二叉排序树的中序遍历,可以得到一个递增的序列。

 

(1) build:

解法1:  将 pair[] 按照 b 大到小排序,这样的话,第一个,肯定就是树的根节点,继续遍历 pair[],按照 a 的值来分配这个结点的位置。

    比如 t->a > insert.a , 这样的话,就往t右子树继续找,如果t->a < insert.a ,就往t右子树继续找,每次t 从根节点开始。

    这样的效率为 Nlog(N);

解法2: 将 pair[] 按照 a 小到大排序,然后在遍历 pair[] 来构建树,因为排序过,所以带插入地 insert 肯定是在当前树中 a 最大的那个,

    这样就会出现两种情况: 1. insert.b > t.b ,则,insert 取代 t 的位置,然后 insert.left = t;

               2.insert.b < t.b ,则,继续与 t.right.b 比较,因为,insert.a 是当前最大,肯定去右边,直至出现 1 的情况,或者到一个空子树,则插入。

    这样的效率也是为 Nlog(N);

解法3:在解法2的基础上改进,因为每次都是从根节点开始进行比较,就会多需要一点时间,然后,我们就用一个 stack 来保存 根节点,根节点的右子树的结点(栈底为根节点) .....因为插入的 a 是最大的,肯定先跟最右的比较,1.如果 insert.b < stack.top.b ,则,stack.top.right = insert.,然后多了个右结点,进栈;2.如果 insert.b > stack.top.b , 则说明,需要回溯上去,再跟 stack--.top.b 比较,如果出现 1 的情况,则,在那之前的右子树,成为 insert.left. insert 进栈;或者出现,所有栈都出去了,说明这个 insert 即将成为新的树根。利用空间换时间,效率为 O(N);

 

(2)insert();

解法: 先按照 二叉排序树的性质,按a的大小将其插入为一个叶子结点,插入之后,进行 b 的判断,如果是左子树插入,且 插入的 b 比较大,则以他的父节点进行一次右旋转,反之,如果是在右子树插入,且插入的 b 比较大,则以他的父节点进行一次左旋转;回溯到根结点.

   

void treap_insert(treap_node*&a,int label,int p)
    {
        if(!a)
        {
            a=new treap_node;
            a->label=label;
            a->p=p;
        }
        else if(label<a->label)
        {
            treap_insert(a->left,label,p);
            if(a->left->p>a->p)
                treap_right_rotate(a);
        }
        else
        {
            treap_insert(a->right,label,p);
            if(a->right->p>a->p)
                treap_left_rotate(a);
        }
    }

 

2015-阿里C++研发附加题第一题

标签:

原文地址:http://www.cnblogs.com/cycxtz/p/4779658.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!