PAT 1119. Pre- and Post-order Traversals (30)

本文介绍了一种根据给定的二叉树前序和后序遍历序列,输出对应的中序遍历序列的方法。当解决方案不唯一时,提供一种可行的中序遍历序列。此外,还探讨了如何判断中序遍历是否唯一。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1119. Pre- and Post-order Traversals (30)

时间限制
400 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Special
作者
CHEN, Yue

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
Sample Output 1:
Yes
2 1 6 4 7 3 5
Sample Input 2:
4
1 2 3 4
2 4 3 1
Sample Output 2:
No
2 1 3 4

自己的代码太繁琐。直接贴别人精髓的把。

题目大意:给出一棵树的结点个数n,以及它的前序遍历和后序遍历,输出它的中序遍历,如果中序遍历不唯一就输出No,且输出其中一个中序即可,如果中序遍历唯一就输出Yes,并输出它的中序
分析:用unique标记是否唯一,如果为1就表示中序是唯一的。

已知二叉树的前序和后序是无法唯一确定一颗二叉树的,因为可能会存在多种情况,这种情况就是一个结点可能是根的左孩子也有可能是根的右孩子,如果发现了一个无法确定的状态,置unique = 0,又因为题目只需要输出一个方案,可以假定这个不可确定的孩子的状态是右孩子,接下来的问题是如何求根结点和左右孩子划分的问题了,首先我们需要知道树的表示范围,需要四个变量,分别是前序的开始的地方prel,前序结束的地方prer,后序开始的地方postl,后序结束的地方postr,前序的开始的第一个应该是后序的最后一个是相等的,这个结点就是根结点,以后序的根结点的前面一个结点作为参考,寻找这个结点在前序的位置,就可以根据这个位置来划分左右孩子,递归处理



[cpp] view plain copy print?
#include <cstdio>  
#include <vector>  
using namespace std;  
vector<int> ans;  
int *pre, *post, unique = 1;  
  
int findFromPre (int x, int l, int r) {  
    for (int i = l; i <= r; i++) {  
        if (x == pre[i]) {  
            return i;  
        }  
    }  
    return -1;  
}  
  
void setIn (int prel, int prer, int postl, int postr) {  
    if (prel == prer) {  
        ans.push_back(pre[prel]);  
        return;  
    }  
    if (pre[prel] == post[postr]) {                                  //精髓 
        int x = findFromPre(post[postr - 1], prel + 1, prer);      
        if (x - prel > 1) {                                          //精髓
            setIn(prel + 1, x - 1, postl, postl + x - prel - 2);  
            ans.push_back(post[postr]);  
            setIn(x, prer, postl + x - prel - 2 + 1, postr - 1);  
        } else {  
            unique = 0;  
            ans.push_back(post[postr]);                                           //  当成左结点一样可以通过:  setIn(x, prer, postl, postr - 1);
            setIn(x, prer, postl + x - prel - 2 + 1, postr - 1);                  //                            ans.push_back(post[postr]);
        }  
    }  
}  
  
int main() {  
    int n = 0;  
    scanf("%d", &n);  
    pre = new int [n];  
    post = new int [n];  
    for (int i = 0; i < n; i++) {  
        scanf("%d", &pre[i]);  
    }  
    for (int i = 0; i < n; i++) {  
        scanf("%d", &post[i]);  
    }  
    setIn(0, n - 1, 0, n - 1);  
    printf("%s\n", unique ? "Yes" : "No");  
    printf("%d", ans[0]);  
    for (int i = 1; i < ans.size(); i++) {  
        printf(" %d", ans[i]);  
    }  
    printf("\n");  
    return 0;  
}  


《C++编程实例100篇》是一本深入实践、极具价值的编程教程,它针对C++编程语言提供了丰富的实例,旨在帮助读者更好地理解和掌握C++的各项特性与编程技巧。这本书的经典之处在于它将理论与实践相结合,通过100个精心设计的编程实例,覆盖了C++的各个核心领域,包括基础语法、面向对象编程、模板、异常处理、STL(标准模板库)等。 我们来探讨C++的基础语法。C++是C语言的增强版,它保留了C语言的高效性和灵活性,并引入了类、对象和继承等面向对象编程概念。基础语法包括变量声明、数据类型、运算符、控制结构(如if语句、for循环、while循环)、函数的定义和调用等。在实例中,你可能会遇到如何编写简单的程序,如计算两个数的和,或者实现一个简单的猜数字游戏。 C++的面向对象编程是其一大特色。通过类和对象,你可以构建复杂的软件系统。类是对象的蓝图,它定义了对象的属性和行为。实例化一个类,就是创建一个具体的对象。继承允许你创建新的类,这些类从现有的类派生,共享其属性和方法,同时可以添加新的功能。多态性是面向对象的另一个关键特性,它使得不同类型的对象可以对同一消息作出不同的响应。这些概念在实例中会以各种形式展现,例如设计一个图形界面的类层次,或实现一个简单的模拟游戏。 接下来是模板,C++的模板功能让代码更加通用,可以处理不同类型的数据。模板分为函数模板和类模板,前者可以创建泛型函数,后者可以创建泛型类。通过模板,你可以编写出高效且灵活的代码,比如实现一个通用的排序算法。 异常处理是C++中用于处理程序运行时错误的机制。当程序出现异常情况时,可以抛出一个异常,然后在适当的点捕获并处理这个异常。这使得代码能够优雅地处理错误,而不是让程序崩溃。实例中可能会有涉及文件操作或网络通信时可能出现的异常处理示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值