题目大意:给出先序和中序序列,输出后序遍历的第一个数。
一开始直接使用常规的先序和中序序列构造树的方法,然后进行后序遍历输出,有两个测试点超时。
于是考虑优化,因为建树过程是从左子树到右子树进行递归的,那么后序遍历输出的第一个数,应该是建树过程中第一个叶子节点,也就是建树过程中第一个左右孩子都为空的节点,也就是建树过程中,第一个在中序序列里的,左边剩余元素leftNum == 0, 右边剩余元素 rightNum == 0的元素。按照这一思路,避免了后序遍历这一步骤,但还是有一个测试点超时。
思考了一下,应该是因为节点数过多(50000个),然后每次在中序序列中寻找元素 node->data 所在的位置这一步时间消耗很大,所以直接用map<int,int>来存储先序序列中每个元素在中序遍历中的位置,避免循环查找。
AC代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstring>
using namespace std;
struct Node
{
int data;
Node* left;
Node* right;
Node(int data)
{
this->data = data;
this->left = NULL;
this->right = NULL;
}
};
void createFromPreIn(Node*& node, vector<int> &pre, map<int,int> &mp, int prel, int prer, int inl, int inr, int &printCount)
{
if(prel > prer || printCount) return;
if(node == NULL) node = new Node(pre[prel]);
int i = mp[node->data];
int leftNum = i - inl;
int rightNum = inr - i;
if(leftNum == 0 && rightNum == 0 && printCount == 0)
{
printf("%d", node->data);
printCount++;
return;
}
createFromPreIn(node->left, pre, mp, prel+1, prel+leftNum, inl, i-1, printCount);
createFromPreIn(node->right, pre, mp, prel+leftNum+1, prer, i+1, inr, printCount);
}
int main()
{
int N;
cin >> N;
vector<int> pre(N);
map<int, int> mp;
for (int i = 0; i < N; ++i)
{
scanf("%d", &pre[i]);
}
for (int i = 0; i < N; ++i)
{
int tmp;
scanf("%d", &tmp);
mp[tmp] = i;
}
Node* root = NULL;
int printCount = 0;
createFromPreIn(root, pre, mp, 0, N-1, 0, N-1, printCount);
return 0;
}