看别人的题解基本都是递归建树,然后找最下的点,但是我这个方法应该会快很多,
因为中序遍历的特性,从左向右的数再树中的位置都是一个没有左子树的节点
可以循环查找,假如有如下树
中序遍历:2 4 6 7 5 3 1
先序遍历 1 2 3 4 5 6 7
首先找到中序遍历的前两个数,2,4,在前序遍历的位置分别为pos1(1),pos2(3),显然pos1<pos2,即前序遍历中2比4先遍历到,然后位置向后移动,找到中序遍历的第二个数和第三个数在前序遍历中的位置,
即4 6,只需此时的pos1仍然小于pos2,继续移动,即6 7,此时pos1仍然小于pos2,继续移动,即7 5,此时pos1>pos2循环结束,pos1位置的元素7即为后序遍历第一个元素,QAQ,是不是很简单,很快速
程序中用一个map定位元素在先序遍历中的位置,如果你之前用过他来定位中序遍历位置建树,你应该不陌生,然后还要注意n==1,就直接输出那个点就行了.
代码:
#include<iostream> #include<queue> #include<string.h> #include<string> #include<map> #include<vector> #include<algorithm> #include<cmath> #include<set> using namespace std; const int maxn = 5e4 + 1; const int maxm = 1e6 + 1; #define INT_MAX 0x7777777 typedef long long ll; inline int read() { int X = 0; bool flag = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-') flag = 0; ch = getchar(); } while (ch >= '0' && ch <= '9') { X = (X << 1) + (X << 3) + ch - '0'; ch = getchar(); } if (flag) return X; return ~(X - 1); } int n; vector<int>pre, ino; map<int, int>M; int main() { n = read(); pre.resize(n); ino.resize(n); for (int i = 0; i < n; i++) { pre[i] = read(); M[pre[i]] = i; } for (int i = 0; i < n; i++) { ino[i] = read(); } if (n == 1){ printf("%d\n", pre[0]); return 0; } int i=0; int pos1 = M[ino[i]], pos2 = M[ino[i+1]]; while(pos1<pos2){ i+=1; pos1=pos2; pos2=M[ino[i+1]]; } printf("%d\n",ino[i]); return 0; }