PAT 1119. Pre- and Post-order Traversals (30) (根据前序后序求中序)

本文探讨了通过前序和后序遍历来判断二叉树中序遍历唯一性的方法。详细介绍了如何根据两种遍历方式确定二叉树结构,并提供了一个具体的实现案例。

题意:给你一棵树的前序和后序遍历,问你它的中序遍历是否唯一,并且给出任意一种中序遍历。


思路:判断中序遍历是否唯一,我们可以通过每个非叶子节点是否都是有两个孩子,如果只有一个孩子,那他的子树既可以是左子树又可以是又子树,所以就不唯一了。


那怎么判断是否有只有一个孩子的结点。

可以看看这个博客:点击打开链接

已知前序遍历和后序遍历序列,是无法确定一棵二叉树的,原因在于如果只有一棵子树可能是左孩子也有可能是右孩子。由于只要输出其中一个方案,所以假定为左孩子即可。下面就是如何根据前序和后序划分出根节点和左右孩子,这里需要定义前序和后序的区间范围,分别为[preL,preR],[postL,postR]。  

  一开始区间都为[1,n],可以发现前序的第一个和后序的最后一个为根节点root,前序的第二个值val为其某子树的根节点(但还无法确定是左孩子or右孩子)。在后序中找对应的值所在的位置postIdx,则postIdx之前的节点均为val的孩子节点,统计其个数num。那么我们就可以划分区间:  

若num个数=preR-preL-1,即val后面的个数都是其子节点,那么二叉树不唯一,将其作为root的左子树处理。

否则划分为左子树区间和右子树对应的前序和后序区间,顺便更新下root的左孩子preL+1,右孩子preL+num+2:
preOrder:[preL+1,preL+num+1],postOrder:[postL,postIdx];
preOrder:[preL+num+2,preR],postOrder:[postIdx+1,postR-1];
然后递归划分即可


拿样例举例:
1 (2) [3 {4 6 7} <5>]
(2) [{6 7 4} <5> 3] 1
不同的括号对应不同的子树区间
第一次递归划分了(2)-(2),[3 4 6 7 5]-[6 7 4 5 3]
由于(2)只有一棵,不继续划分。
第二次递归划分了{4 6 7}-{6 7 4},<5>-<5>
第三次递归划分了(6)-(6),(7)-(7)


代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 35;
int n, cnt, pre[maxn], in[maxn], post[maxn];
bool isUnique;

void build(int preL, int preR, int postL, int postR)
{
    if(preL == preR) { in[cnt++] = pre[preL]; return ; }
    if(preL > preR) return ;
    int idx;
    for(int i = postL; i < postR; i++)
    {
        if(pre[preL+1] == post[i])
        {
            idx = i;
            break;
        }
    }
    int numL = idx-postL;
    if(preR-preL-1 == numL) isUnique = 0;
    build(preL+1, preL+1+numL, postL, idx);
    in[cnt++] = pre[preL];
//    cout << pre[preL] << endl;
    build(preL+numL+2, preR, idx+1, postR-1);
}

int main(void)
{
    while(cin >> n)
    {
        cnt = 1;
        isUnique = 1;
        for(int i = 1; i <= n; i++) scanf("%d", &pre[i]);
        for(int i = 1; i <= n; i++) scanf("%d", &post[i]);
        build(1, n, 1, n);
        puts(isUnique ? "Yes" : "No");
        for(int i = 1; i <= n; i++) printf("%d%c", in[i], i==n ? '\n' : ' ');
    }
    return 0;
}


American Heritage 题目描述 Farmer John takes the heritage of his cows very seriously. He is not, however, a truly fine bookkeeper. He keeps his cow genealogies as binary trees and, instead of writing them in graphic form, he records them in the more linear tree in-order" and tree pre-order" notations. Your job is to create the `tree post-order" notation of a cow"s heritage after being given the in-order and pre-order notations. Each cow name is encoded as a unique letter. (You may already know that you can frequently reconstruct a tree from any two of the ordered traversals.) Obviously, the trees will have no more than 26 nodes. Here is a graphical representation of the tree used in the sample input and output: C / \ / \ B G / \ / A D H / \ E F The in-order traversal of this tree prints the left sub-tree, the root, and the right sub-tree. The pre-order traversal of this tree prints the root, the left sub-tree, and the right sub-tree. The post-order traversal of this tree print the left sub-tree, the right sub-tree, and the root. ---------------------------------------------------------------------------------------------------------------------------- 题目大意: 给出一棵二叉的中遍历 (inorder)前序遍历 (preorder)它的后序遍历 (postorder)。 输入描述 Line 1: The in-order representation of a tree. Line 2: The pre-o rder representation of that same tree. Only uppercase letter A-Z will appear in the input. You will get at least 1 and at most 26 nodes in the tree. 输出描述 A single line with the post-order representation of the tree. 样例输入 Copy to Clipboard ABEDFCHG CBADEFGH 样例输出 Copy to Clipboard AEFDBHGC c语言,代码不要有注释
最新发布
06-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值