1138 Postorder Traversal (25 分)

博客探讨了如何根据前序和中序序列生成后序遍历序列,特别是在仅需输出后序序列第一个元素的情况下如何优化算法。文章通过两个版本的代码实现,V1完整生成后序序列,V2则通过提前退出递归来提高效率。主要涉及二叉树遍历、递归和回溯法等概念。
摘要由CSDN通过智能技术生成

跟着柳婼学姐学习的笔记ヾ(≧▽≦*)o

原题目: 1138 Postorder Traversal (25 分)

题意

给出前序和中序序列,
👉要求输出后序遍历序列的第一个元素。

分析 V1

通过前序和中序序列生成后序序列。

  1. 关键:利用前序序列第一个元素总是根结点的特点,找到根结点在中序序列中的位置,将前序和中序序列划分为左子树区间和右子树区间,再往下递归。
  2. 递归式:生成后序序列,则逻辑同后序遍历;“访问根结点”操作——压入post数组中。
  3. 递归边界:当划分区间不成立,即区间小于0时【注意:不能取等号】。

CODE V1

#include <iostream>
#include <vector>
using namespace std;
int n;
vector<int> pre, in, post;
void createPost(int prel, int prer, int inl, int inr);
int main()
{
    cin >> n;
    pre.resize(n);
    in.resize(n);
    for ( int i=0; i<n; i++ ) cin >> pre[i];
    for ( int i=0; i<n; i++ ) cin >> in[i];
    createPost(0, n-1, 0, n-1);
    cout << post[0];
    
    return 0;
}
void createPost(int prel, int prer, int inl, int inr){
    if ( prel>prer ) return;  //递归边界:先序序列的区间小于0
    //pre[prel]为根结点,找到其在中序序列中的位置(下标)
    int k = inl;  //当前根结点在中序序列中的位置
    while( pre[prel]!=in[k] ) k++;  //循环结束后,找到位置
    //后序遍历(递归式)
    createPost(prel+1, prel+k-inl, inl, k-1);  //往左子树递归
    createPost(prel+k-inl+1, prer, k+1, inr);  //往右子树递归
    post.push_back(in[k]);   //访问根结点:将后序序列放入post数组中
}

分析 V2

题目只要求输出后序序列的第一个元素,故其实并不需要生成完整的后序序列——考虑 提前退出递归

  1. 单独设置一个标记flag——用于① 控制输出(否则会在回退的路上胡乱输出)② 提前退出递归
  2. 递归边界:改用中序区间——在V1中,createPost函数的参数prer其实用处不大,可以省去,并且改用中序序列的区间作为递归边界。

CODE V2

#include <iostream>
#include <vector>
using namespace std;
int n;
vector<int> pre, in;
bool flag = false;  //标记是否输出第一个后序序列元素,默认为未输出false
void Post(int prel, int inl, int inr);
int main()
{
    cin >> n;
    pre.resize(n);
    in.resize(n);
    for ( int i=0; i<n; i++ ) cin >> pre[i];
    for ( int i=0; i<n; i++ ) cin >> in[i];
    Post(0, 0, n-1);
    
    return 0;
}
void Post(int prel, int inl, int inr){
    if ( inl>inr || flag ) return;  //递归边界:①先序序列的区间小于0,②已经按题意输出
    //pre[prel]为根结点,找到其在中序序列中的位置(下标)
    int k = inl;  //当前根结点在中序序列中的位置
    while( pre[prel]!=in[k] ) k++;  //循环结束后,找到位置
    //后序遍历(递归式)
    Post(prel+1, inl, k-1);  //往左子树递归
    Post(prel+k-inl+1, k+1, inr);  //往右子树递归
    if ( !flag ){   //有条件地访问根结点
        cout << in[k];
        flag = true;   //标记为已输出
    }
}

知识点

  1. 前序+中序 转 后序”的逻辑——关键在于找根结点的中序位置后分左右子树区间。👉 传送门:&3 给定先序和中序遍历序列,重建二叉树⭐⭐【重要】
  2. 回溯法——在到达递归边界前由于某些事实可以直接返回上一层(感觉其实也是增加了一条递归边界啦(~ ̄▽ ̄)~)。👉初次间面传送门:n皇后问题的算法改进

词汇

CHUNK释义
corresponding binary tree对应的,相应的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值