PAT 1138 Postorder Traversal(25 分)

博客围绕根据二叉树前序和中序求后序第一个数字的问题展开。常规思路是建树,但可不用建树,将问题转化为找遍历中第一个叶子节点。通过分析前序和中序遍历特点,找到满足条件的点。还提到优化查找子树根节点的方法,将复杂度从O(n)降到O(1)。

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

这个题的意思是给你一颗二叉树的前序和中序,让你求出这棵树后序的的第一个数字。

常规的思路应该是利用前序和中序建立一颗二叉树。

但是题目的要求是只需要后序的第一个数字,那我们可以考虑不用建树来解决这个问题。

第一次经过时输出是前序遍历,第二次时是中序,第三次时是后序。

那么一个点如果后序遍历的时候第一次经过就输出,那么说明它没有孩子节点。

那我们的问题就转变为找到遍历过程中第一个叶子节点(没有孩子的节点)

怎么找到他呢,二叉树的前序遍历和中序遍历的大致如下

中序遍历根节点的左边是左子树,右边是右子树。

前序遍历和第一个节点是根节点,根节点右侧的第一个节点是左子树的根节点。

这个叶子节点一定在左子树的左子树的左子树的.........上。不然不返回的话,这棵树就是一条直线。

叶子节点没有孩子节点,那么在中序遍历中它的左右子树区域都为空。

所以我通过遍历左子树的左子树的。。。。找到一个在中序上左右皆为空的点。

这个问题到这里就完了,但有一个小小的骚操作,在中序上找子树的根节点的时候,我一开始是用循环遍历找到这个点了,但是后来交了一次,超时了,有一个测试点始终过不去。

然后我就用一个一个数组来存储这个点在inorder上的位置,复杂度从O(n)降到了O(1)。

最后耗时25ms过掉这个题。

 

 

 

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<map>
using namespace std;

int preorder[51015];
int inorder[51015];
int node[10000005];
bool vis[51015];
int result=0;
int n,root;

void fun(int num)
{
    root = preorder[num];

    vis[ node[root] ] = 1;
    
    if(node[root] == 0 && vis[1]==1)
    {
        result = 0;
        return ;
    }
    else if(node[root] == n-1 && vis[n-2]==1)
    {
        result = n-1;
        return ;
    }

    if(vis[node[root]-1]==1 && vis[node[root]+1]==1)
    {
        result = node[root];
        return ;
    }

    fun(++num);

}


int main()
{

    scanf("%d",&n);

    for(int i=0;i<n;i++)
    {
        scanf("%d",&preorder[i]);
    }

    for(int i=0;i<n;i++)
    {
        scanf("%d",&inorder[i]);
        node[ inorder[i] ] = i;
    }


    fun(0);

    printf("%d\n",inorder[result]);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值