PAT 甲级 1138 Advanced Level 1138 Postorder Traversal(25 分)低时耗AC

 

原题地址:https://pintia.cn/problem-sets/994805342720868352/problems/994805345078067200

题目正文:

1138 Postorder Traversal(25 分)

Suppose that all the keys in a binary tree are distinct positive integers. Given the preorder and inorder traversal sequences, you are supposed to output the first number of the postorder traversal sequence of the corresponding binary tree.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤ 50,000), the total number of nodes in the binary tree. The second line gives the preorder sequence and the third line gives the inorder sequence. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the first number of the postorder traversal sequence of the corresponding binary tree.

Sample Input:

7
1 2 3 4 5 6 7
2 3 1 5 4 7 6

Sample Output:

3

题目要求:

作者: CHEN, Yue

单位: 浙江大学

时间限制: 650ms

内存限制: 64MB

代码长度限制: 16KB

说明:

题目的要求就是根据二叉树的先序和中序序列,求后序的第一个元素。题目中给了50000个数据,量还是很大的,所以建树然后根据完整的二叉树再后序遍历,很可能会超时。因为只需要求第一个输出的元素,所以我们找到第一个输出元素就提前停止程序就好。后序遍历的规则就是,如果左子树存在,则先考虑左子树,如果左子树不存在而右子树存在,则先考虑右子树,如果左右子树均不存在,则输出当前的根节点。所以,我们只需要找到第一个跟据后序遍历访问到的左右子树均不存在的根节点。

解题中用到了unordered_map,这种数据结构使用哈希桶算法实现底层,和使用红黑树实现底层的map相比,访问速度更快,但是遍历效率较低。

别的不多说了,需要的说明都可以在zhu's注释中找到。题目给出了650 ms的时间限制,这里可以实现19 ms AC。

完整AC代码:

#include<cstdio>
#include<unordered_map>
using namespace std;
int pre[50010],in[50010];
/*
    mp[in-seq-data]=in-seq-index, for fast indexing of in-seq-elements.
    The indexing efficiency of unordered_map is superior than that of map,
    but the traversal efficiency of unordered_map is degenerated
    compared with ordered_map.
*/
unordered_map<int,int> mp;
/*
    a fast version of scanf("%d",&variable);
*/
int read(){
    int input=0;
    char a=getchar();
    while(a<'0' || a>'9')
        a=getchar();
    while(a>='0' && a<='9'){
        input=input*10+a-'0';
        a=getchar();
    }
    return input;
}
int main(){
    int n;                  //number of total elements
    scanf("%d",&n);
    for(int i=0;i<n;++i)
        pre[i]=read();
    for(int i=0;i<n;++i){
        in[i]=read();       //in[in-seq-index]=in-seq-data;
        mp[in[i]]=i;        //mp[in-seq-data]=in-seq-index
    }
    /*
        The aim is to find the smallest subtree (1 element) according to post-order-traversal rules.
        If the current node has a left subtree, consider the left subtree.
        Or if the current node has no left subtree, consider the right subtree.
        ps  :   the index of the first element of the current subtree in the pre-order-sequence, ie. the sub-root index.
        pe  :   the index behind the last element of the current subtree in the pre-order-sequence.
        is  :   the index of the first element of the current subtree in the in-order-sequence.
        i   :   temporary variable to store the root index of the current subtree in the in-order-sequence.
    */
    int ps=0,pe=n,is=0,i;
    while(ps<pe){           //if subtree exist
        if(ps+1==pe){       //if subtree has only one element, print the element and break the loop;
            printf("%d",pre[ps]);
            break;
        }
        i=mp[pre[ps]];      //acquire the root index of the current subtree in the in-order-sequence.
        if(i!=is){          //if current subtree has left subtree, then i-is should be number of nodes of the left subtree
            ++ps;           //change ps to new left subtree
            pe=ps+i-is;     //change pe to new left subtree
        }else{              //if current subtree has no left subtree
            ++ps;           //change ps to new right tree
            ++is;           //the index of the first element of the new subtree in the in-order-sequence.
        }
    }
    return 0;
}

运行时间截图:

参考:https://www.liuchuo.net/archives/4208

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值