题目
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
文章大意
给出先序遍历和中序遍历,输出后序遍历的第一个数
思路
直接先序中序转后序即可,而且找到的是第一个数,因为不用建树,直接输出最底层的左孩子(如果存在)
实现
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> pre;
vector<int> in;
bool flag = false;
void postOrder(int inL, int inR,int preRoot) {//preRoot是数组下标
if (inL > inR || flag == true) return;
//一直从根节点出发找到他的左孩子
int root = inL;
while (in[root] != pre[preRoot]) root++;//得到中序序列中根节点位置
//分别对根节点前后调用该函数,寻找左孩子
postOrder(inL, root - 1, preRoot+1);//如果是左子树,则在先序中的根节点就是前一个先序根节点加1
//如果是右子树,在先序的中的根节点,为前一个先序根节点也就是pre,加上现在中序中的根节点前面的长度root-inR,最后加上1
//为什么不是直接root+1。因为当inL不为0的时候,中序中的根节点数组下标root与下一个前序根节点会随着迭代逐次差一个1
postOrder( root + 1,inR ,preRoot + root - inL + 1);
if (flag == false) {//当迭代到最后一个时,也就是找到的最左左孩子或者右孩子,执行下面语句,更改flag的值,使得返回进行上一层迭代时退出
cout << in[root];
flag = true;
}
}
int main()
{
int n;
cin >> n;
int s;
for (int i = 0; i < n; i++) {
cin >> s;
pre.push_back(s);
}
getchar();
for (int i = 0; i < n; i++) {
cin >> s;
in.push_back(s);
}
postOrder(0, n - 1, 0);
return 0;
}
注意事项和总结
因为这是第一次接触树相关题目,主要参考的柳神的代码,花了好大的功夫才弄清里面的逻辑,开始我一直以为求出中序中根节点位置后,得到的右子树在前序序列中的根节点位置是中序根节点+1(因为左子树是上一个前序序列中的根节点+1),原来不是的,这个随着递归会有变化,只有最开始的时候才行,但随着右子树的左边界变化而变化
//如果是右子树,在先序的中的根节点,为前一个先序根节点也就是pre,加上现在中序中的根节点前面的长度root-inR,最后加上1;为什么不是直接root+1。因为当inL不为0的时候,中序中的根节点数组下标root与下一个前序根节点会随着迭代逐次差一个1
//如果是左子树,则在先序中的根节点就是前一个先序根节点加1
另外要注意的是,要考虑提前退出递归,不然会导致超时