您的位置:首页 > 编程语言 > C语言/C++

阿里巴巴2016年秋季校园招聘C++研发岗在线笔试附加题第一题

2015-08-24 10:45 399 查看
第一次参加在线笔试,没适应节奏,也忘记对题目截图或复制了。下面大概描述一下题目意思:

题目给出了两个结构定义:

struct pair_t {

    int a, b;

};

struct node_t {

    int a, b;

    node_t *left, *right;

};

其中 pair_t 结构表示输入的数据对,node_t 结构表示需要实现的二叉树结构。

1,题目的输入是若干 pair_t 结构的数据,然后要求建立一棵二叉树,要求二叉树的左子树的 a 值小于根节点的 a 值,右子树的 a 值大于根节点的 a 值,且二叉树是一个按 b 值建立的大顶堆。

题目还有个提示:(1)二叉树存在且唯一; (2)先确定根节点。

2,第二问是对于新输入的 pair_t 结构数据,如何插入使其仍然满足该二叉树的性质,因为算法比较复杂,所以只要求给出思路。

(题目大概意思是这样)

 

我解题的思路:

1,

首先按照 pair_t 结构数据的 a 值排序;

然后根据 pair_t 的 b 值找到根节点;

再根据根节点找到左右子树(pair_t 结构数组中,排序之后,在根节点左边的就是左子树,在右边的就是右子树);

然后重复这一过程即可完成建树。

 

第一问的代码:

#include <iostream>

using namespace std;

//输入的数据结构

struct pair_t {

    int a, b;

};

//二叉树节点结构

struct node_t {

    int a, b;

    node_t *left, *right;

};

/*

*   因为要求大顶堆的左子树的 a 值小于根节点的 a 值,且右子树的 a 值大于根节点的 a 值,所以按 a 排序;

*   下面是快排函数

*/

void sort_pair_a(pair_t* pair, int start, int end)

{

    if(start >= end)

        return ;

    int begin = start;

    int finish = end;

    pair_t value;

    value = pair[start];

    while(start < end) {

        for( ; start < end; --end)

            if(pair[end].a < value.a) {

                pair[start++] = pair[end];

                break;

            }

        for( ; start < end; ++start)

            if(pair[start].a > value.a) {

                pair[end--] = pair[start];

                break;

            }

    }

    pair[start] = value;

    sort_pair_a(pair, begin, start);

    sort_pair_a(pair, start+1, finish);

}

/*

*   下面是根据数据对的 b 值建大顶堆;

*   试题中其实已经提示大家要先找根节点,所谓根节点,也就是大顶堆的顶,即 b 值最大的数据对;

*   由于通过排序将数据对按 a 的升序排列,所以根据找到的根节点就可以很轻松的确定左右子树了,然后重复这一过程建树;

*

*   按理说对 pair[] 只需要一次排序即可,但是试题只要求写出 build() 函数,所以我这里的快排是放在 build() 函数中的;

*   我在想,其实不排序也可以的,只要先遍历一遍找到根节点,然后再遍历找到左子树和右子树的节点,再建树就可以了;

*   话说回来,排序后理解起来更容易,操作也简单,反正排序函数不难敲对吧 ^.^

*/

node_t* build(pair_t* pair, int n)

{

    sort_pair_a(pair, 0, n-1);    //对数组 pair 按 a 的值做升序排序。这个排序函数其实可以放在 main() 函数中的,只是题目只要求给出 build() 函数的实现,所以我就放在这里了。

    node_t* T = new node_t;

    pair_t temp;

    temp = pair[0];

    int i, loc=0;

    //找根节点

    for(i=1; i < n; i++)

        if(temp.b < pair[i].b) {

            temp = pair[i];

            loc = i;

        }

    T->a = temp.a;

    T->b = temp.b;

    //左子树

    if(loc > 0)

        T->left = build(pair, loc); //数组pair中的数从位置 0 开始存,所以这里的长度是 loc 而不是 loc-1;

    else

        T->left = NULL;

    //右子树

    if(n-loc-1 > 0)

        T->right = build(pair+loc+1, n-loc-1);    //和上一条语句一样,要注意一下数组起始位置和长度中的 +1 和 -1;

    else

        T->right = NULL;

    return T;   //返回根节点

}

//先序遍历

void print_prior(node_t* p)

{

    if(p == NULL)

        return ;

    if(p != NULL)

        cout<<"("<<p->a<<", "<<p->b<<") ";//<<endl;

    print_prior(p->left);

    print_prior(p->right);

}

//中序遍历

void print_mid(node_t* p)

{

    if(p == NULL)

        return ;

    print_mid(p->left);

    if(p != NULL)

        cout<<"("<<p->a<<", "<<p->b<<") ";//<<endl;

    print_mid(p->right);

}

//后序遍历

void print_last(node_t* p)

{

    if(p == NULL)

        return ;

    print_last(p->left);

    print_last(p->right);

    if(p != NULL)

        cout<<"("<<p->a<<", "<<p->b<<") ";//<<endl;

}

#define N 1000

int main()

{

    pair_t pair
;

    int n;

    cin>>n;

    for(int i=0; i < n; i++)

        cin>>pair[i].a>>pair[i].b;

    node_t* T = build(pair, n);

    print_prior(T);

    cout<<endl;

    print_mid(T);

    cout<<endl;

    print_last(T);

    cout<<endl;

    return 0;

}

/*

测试样例:

6

5 8

2 10

4 3

1 5

0 2

9 1

*/

 

 

2,第二问我之前的思路:

1,首先将要插入的节点的 b 值与根节点的 b 值比较:

              1)如果小于根节点的 b 值,转步骤 2;

              2)如果大于根节点的 b 值,则将该节点与根节点交换,让它成为新的根节点,然后用原来的根节点作为要插入的节点,重复步骤 1;

2,将该节点的 a 值与根节点的 a 值进行比较:

              1)如果小于根节点的 a 值,则将其插入左子树,转步骤 1;

              2)如果大于根节点的 a 值,则将其插入右子树,转步骤 1;  

//题目已经说明,输入的数据满足要求,二叉树存在且唯一,所以不会存在 a 和 b 值都相等的情况,即不会出现完全一样的节点。

 

不过后来发现第二问的思路肯定是不对的,因为这个思路可能会破坏 a 值的性质,所以正确的思路应该要先根据 a 值找到合适的位置,然后再进行调整;不过暂时还没完全理清头绪,等确定了再更新。

这里给出第 2 问的错误思路,是告诉和我有过这种思路的同学再思考一下。

 

 

上面就是我对该题的理解和解答。这篇博客并非给出标准的答案,只是跟大家交流,如果博客中存在错误,欢迎大家指出,谢谢!

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: