一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,
- 其左子树中所有结点的键值小于该结点的键值;
- 其右子树中所有结点的键值大于等于该结点的键值;
- 其左右子树都是二叉搜索树。
所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。
给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。
输入格式:
输入的第一行给出正整数N(<=1000)。随后一行给出N个整数键值,其间以空格分隔。
输出格式:
如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出“YES”,然后在下一行输出该树后序遍历的结果。数字间有1个空格,一行的首尾不得有多余空格。若答案是否,则输出“NO”。
输入样例1:
7 8 6 5 7 10 8 11
输出样例1:
YES 5 7 6 8 11 10 8
输入样例2:
7 8 10 11 8 6 7 5
输出样例2:
YES 11 8 10 7 5 6 8
输入样例3:
7 8 6 8 5 10 9 11
输出样例3:
NO
思路:根据题目中的给出的二叉搜索树的性质及前序遍历,可以轻易的构造出该树,(因为前序遍历,所以第一个节点肯定是根节点。比根节点大的都是右子树,比根节点小的都是左子树,所以每一次只需要找到一个子树的开头和结尾就能找到这个子树的根了)
然后据此推出后序遍历。
题解看到一个人写的超级简洁,这里就不贴我的垃圾代码了,贴大佬的
1 #include <cstdio> 2 #include <vector> 3 using namespace std; 4 bool isMirror; 5 vector<int> pre; 6 vector<int> post; 7 void getpost(int root, int tail) { 8 if(root > tail) return ; 9 int i = root + 1, j = tail; 10 if(!isMirror) { 11 while(i <= tail && pre[root] > pre[i]) i++;////找右子树的第一个节点 12 while(j > root && pre[root] <= pre[j]) j--;////找左子树的最后一个节点 13 } else { 14 while(i <= tail && pre[root] <= pre[i]) i++; 15 while(j > root && pre[root] > pre[j]) j--; 16 } 17 if(i - j != 1) return ; 18 getpost(root + 1, j); 19 getpost(i, tail); 20 post.push_back(pre[root]); 21 } 22 int main() { 23 int n; 24 scanf("%d", &n); 25 pre.resize(n); 26 for(int i = 0; i < n; i++) 27 scanf("%d", &pre[i]); 28 getpost(0, n - 1); 29 if(post.size() != n) { 30 isMirror = true; 31 post.clear(); 32 getpost(0, n - 1); 33 } 34 if(post.size() == n) { 35 printf("YES %d", post[0]); 36 for(int i = 1; i < n; i++) 37 printf(" %d", post[i]); 38 } else { 39 printf("NO"); 40 } 41 return 0; 42 }
附该大佬博客:https://www.liuchuo.net/archives/2155