✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:PAT题解集合
📝原题地址:题目详情 - 1119 Pre- and Post-order Traversals (pintia.cn)
🔑中文翻译:前序和后序遍历
📣专栏定位:为想考甲级PAT的小伙伴整理常考算法题解,祝大家都能取得满分!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree can be determined by a given pair of postorder and inorder traversal sequences, or preorder and inorder traversal sequences. However, if only the postorder and preorder traversal sequences are given, the corresponding tree may no longer be unique.
Now given a pair of postorder and preorder traversal sequences, you are supposed to output the corresponding inorder traversal sequence of the tree. If the tree is not unique, simply output any one of them.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤ 30), the total number of nodes in the binary tree. The second line gives the preorder sequence and the third line gives the postorder sequence. All the numbers in a line are separated by a space.
Output Specification:
For each test case, first printf in a line
Yesif the tree is unique, orNoif not. Then print in the next line the inorder traversal sequence of the corresponding binary tree. If the solution is not unique, any answer would do. It is guaranteed that at least one solution exists. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.Sample Input 1:
7 1 2 3 4 6 7 5 2 6 7 4 5 3 1
- 1
- 2
- 3
Sample Output 1:
Yes 2 1 6 4 7 3 5
- 1
- 2
Sample Input 2:
4 1 2 3 4 2 4 3 1
- 1
- 2
- 3
Sample Output 2:
No 2 1 3 4
- 1
- 2
给定一组前序遍历和后序遍历,请你输出对应二叉树的中序遍历。
如果树不是唯一的,则输出任意一种可能树的中序遍历即可。
由于结果可能不唯一,所以我们可以直接暴力枚举所有情况,以左子树包含的结点数量为依据进行枚举:
l1 > r1 ,则说明当前子树已经遍历完,直接返回 1 即可;如果 pre[l1] != post[r2] ,则说明当前这种遍历情况不能构成二叉树,因为前序遍历数组的第一个和后序遍历数组的最后一个元素都是根结点,所以两者必须相等。to_string 库函数,它的作用是将数字转换成字符串。#include
using namespace std;
const int N = 40;
int n;
int pre[N], post[N];
int dfs(int l1, int r1, int l2, int r2, string& in)
{
if (l1 > r1) return 1;
if (pre[l1] != post[r2]) return 0; //判断根结点是否相等
int cnt = 0;
for (int i = l1; i <= r1; i++) //遍历左子树包含的结点数量
{
string lin, rin; //记录左右子树中序遍历的结果
int lcnt = dfs(l1 + 1, i, l2, l2 + i - l1 - 1, lin); //记录左子树的合法方案数
int rcnt = dfs(i + 1, r1, l2 + i - l1 - 1 + 1, r2 - 1, rin); //记录右子树的合法方案数
if (lcnt && rcnt)
{
in = lin + to_string(pre[l1]) + " " + rin; //往结果集中加入当前结点
cnt += lcnt * rcnt; //记录有多少合法方案数
if (cnt > 1) break; //剪枝,只要方案数大于1个,就直接break
}
}
return cnt;
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++) cin >> pre[i];
for (int i = 0; i < n; i++) cin >> post[i];
string in;
int cnt = dfs(0, n - 1, 0, n - 1, in);
if (cnt == 1) puts("Yes"); //方案唯一
else puts("No"); //方案不唯一
in.pop_back(); //去掉末尾空格
cout << in << endl;
return 0;
}