原题地址: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;
}