1119. (重、错) Pre- and Post-order Traversals

题目大意

给定一棵树的结点个数n,以及它的前序遍历和后序遍历,输出它的中序遍历;

如果中序遍历不唯一就输出No,且输出其中一个中序即可,如果中序遍历唯一就输出Yes,并输出它的中序

思路:(转载

先序+后序 无法判断二叉树的唯一性

  • 先序第一个节点是根节点,紧接着第二个节点是根节点的左节点还是右节点?
  • 在后序中查找 先序中的第二个节点,
  1. 如果后序中的该位置 到 最后(也就是后序中根节点位置) 还有其他数的话,可以判断,先序中第二个节点肯定左节点(反证法。。。)
  2. 当中间没有数的时候,就不确定了

例如:

前序序列:1 2 3 4
后序序列:2 4 3 1

1 为 根,2 接着,2在后序中,与1隔着两个数,所以2一定是1的左节点; 3,4成为1的右子树节点
#include<bits/stdc++.h>
using namespace std;
int n;
bool isUnique = true;
vector<int> preOrder, in, postOrder;

struct Node {
    int val;
    Node* lchild, *rchild;
    Node(int _val = -1){
        val = _val;
        lchild = NULL;
        rchild = NULL;
    }

};

Node* Create(int preL, int preR, int postL, int postR)
{
    Node* root = new Node(preOrder[preL]);
    if (preL == preR) return root;
    int k;
    for (k = postL; k < postR; k++){ // 后序找 pre[preL + 1]
        if (postOrder[k] == preOrder[preL + 1]) break;
    }
    // 在后序中查找 先序中的第二个节点
    // 如果后序中的该位置 到 最后(也就是后序中根节点位置) 还有其他数的话,
    // 可以判断,先序中第二个节点肯定左节点(反证法。。。)
    if (postR - k - 1 > 0){
        int numLeft = k - postL + 1;
        root->lchild = Create(preL + 1, preL + numLeft, postL, k);
        root->rchild = Create(preL + 1 + numLeft, preR, k + 1, postR - 1);
    }
    else {
        isUnique = false;
        //假定第二个节点是根节点的右节点
        root->rchild = Create(preL + 1, preR, postL, postR - 1);
    }
    return root;
}

void inOrder(Node* root){
    if (root != NULL){
        inOrder(root->lchild);
        in.push_back(root->val);
        inOrder(root->rchild);
    }
}

int main()
{
    scanf("%d", &n);
    preOrder.resize(n);
    postOrder.resize(n);
    for (int i = 0; i < n; i++) scanf("%d", &preOrder[i]);
    for (int i = 0; i < n; i++) scanf("%d", &postOrder[i]);
    Node* root = Create(0, n - 1, 0, n - 1);
    inOrder(root);
    printf("%s\n%d", isUnique == true ? "Yes" : "No", in[0]);
    for (int i = 1; i<n; i++) printf(" %d", in[i]);
    printf("\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fuqia/p/9503133.html
今日推荐