【PAT甲级 - C++题解】1119 Pre- and Post-order Traversals

简介: 【PAT甲级 - C++题解】1119 Pre- and Post-order Traversals

1119 Pre- and Post-order Traversals


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 Yes if the tree is unique, or No if 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


Sample Input 2:

4
1 2 3 4
2 4 3 1
• 1
• 2
• 3

Sample Output 2:

No
2 1 3 4


题意


给定一组前序遍历和后序遍历,请你输出对应二叉树的中序遍历。

如果树不是唯一的,则输出任意一种可能树的中序遍历即可。


思路


由于结果可能不唯一,所以我们可以直接暴力枚举所有情况,以左子树包含的结点数量为依据进行枚举:


每次递归都要先判断是否满足条件,如果 l1 > r1 ,则说明当前子树已经遍历完,直接返回 1 即可;如果 pre[l1] != post[r2] ,则说明当前这种遍历情况不能构成二叉树,因为前序遍历数组的第一个和后序遍历数组的最后一个元素都是根结点,所以两者必须相等。

遍历左子树包含结点的数量,只要发现合法方案的数量大于一个,就直接退出循环,因为题目只要求输出其中一种合法情况即可。计算合法方案的方法是,获得左子树的合法方案数以及右子树的合法方案数,让两者相乘就是当前遍历情况的合法方案数了。

如果当前情况是满足条件的,就将当前结点加入结果集当中,因为题目要求输出中序遍历结果,所以我们要获得左子树和右子树的中序遍历结果,然后往中间插入当前结点即可。注意,这里用到了 to_string 库函数,它的作用是将数字转换成字符串。

最后判断合法方案数是否唯一,然后输出中序遍历结果。注意,末尾不能有空格,需要手动去掉。

代码

#include<bits/stdc++.h>
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;
}


目录
相关文章
|
C++
【PAT甲级 - C++题解】1040 Longest Symmetric String
【PAT甲级 - C++题解】1040 Longest Symmetric String
66 0
|
算法 C++
【PAT甲级 - C++题解】1044 Shopping in Mars
【PAT甲级 - C++题解】1044 Shopping in Mars
82 0
|
C++
【PAT甲级 - C++题解】1117 Eddington Number
【PAT甲级 - C++题解】1117 Eddington Number
77 0
|
存储 C++ 容器
【PAT甲级 - C++题解】1057 Stack
【PAT甲级 - C++题解】1057 Stack
76 0
|
存储 C++
【PAT甲级 - C++题解】1055 The World‘s Richest
【PAT甲级 - C++题解】1055 The World‘s Richest
79 0
|
C++
【PAT甲级 - C++题解】1051 Pop Sequence
【PAT甲级 - C++题解】1051 Pop Sequence
80 0
|
人工智能 BI C++
【PAT甲级 - C++题解】1148 Werewolf - Simple Version
【PAT甲级 - C++题解】1148 Werewolf - Simple Version
135 0
|
10天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
39 4
|
12天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
35 4
|
1月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
27 4