ruye07

导航

二叉树:由前序+中序遍历重建,求后序遍历

**# 二叉树:由前序+中序遍历重建,求后序遍历

题目原型

P1827 USACO3.4 美国血统 American Heritage

给定二叉树的前序遍历和中序遍历,输出后序遍历。节点为唯一大写字母,最多 26 个。

知识铺垫:三种遍历回顾

         C
        / \
       B   G
      / \  /
     A   D H
        / \
       E   F
遍历 顺序 该树输出
前序 → 左 → 右 C B A D E F G H
中序 左 → → 右 A B E D F C H G
后序 左 → 右 → A E F D B H G C

核心思想:分治递归

给定:pre = "CBADEFGH"  (前序)
      in  = "ABEDFCHG"  (中序)

步骤:
  1. 前序首字符为根 → root = 'C'
  2. 在中序中找到 'C' 的位置 idx = 5
     in:  A B E D F [C] H G
          ← 左子树 → ↑ ←右子树→
            (idx个)       (len-idx-1个)

  3. 切割:
     左子树中序 = in[0:idx]      → "ABEDF"
     左子树前序 = pre[1:1+idx]   → "BADEF"
     右子树中序 = in[idx+1:]     → "HG"
     右子树前序 = pre[1+idx:]    → "GH"

  4. 递归构建左、右子树
  5. 后序排列:左后序 + 右后序 + 根
ASCII 递归过程:

                pre="CBADEFGH"  in="ABEDFCHG"
                root='C'  idx=5
               /                        \
    左: pre="BADEF"             右: pre="GH"
        in="ABEDF"                  in="HG"
        root='B' idx=1              root='G' idx=1
       /          \                /          \
  pre="A"      pre="DEF"      pre="H"      pre=""
  in="A"       in="EDF"       in="H"       in=""
  root='A'     root='D'       root='H'     return ""
  idx=0        idx=1          idx=0
  /     \       /    \         /    \
 ""     ""   pre="E" pre="F"  ""    ""
             in="E"  in="F"
             idx=0   idx=0
             / \     / \
            "" ""   "" ""

后序拼接(自底向上):
  A → A          E→E  F→F     H→H
  A + "" + "" = A
  E + F + D = EFD
  A + EFD + B = AEFDB
  H + "" + G = HG
  AEFDB + HG + C = AEFDBHGC  ✓

代码模板

def build(in_o, pre_o):
    if not pre_o:
        return ''
    root = pre_o[0]                     # 前序第一个 = 根
    idx = in_o.index(root)              # 中序中根的位置

    # 切割四段
    left_in  = in_o[:idx]               # 左子树中序
    right_in = in_o[idx + 1:]           # 右子树中序
    left_pre  = pre_o[1 : 1 + idx]      # 左子树前序
    right_pre = pre_o[1 + idx :]        # 右子树前序

    # 后序 = 左后序 + 右后序 + 根
    return (build(left_in, left_pre) +
            build(right_in, right_pre) +
            root)

边界易错点

1. 输入空格

in_o = input().strip()   # 必须 strip,样例第二行末尾有空格,不然只能过70%样例
pre_o = input().strip()

2. 切片范围

左子树节点数 = idx 个

前序切分:
  pre[0]       → 根(跳过)
  pre[1:1+idx] → 左子树前序(紧接根后,取 idx 个)
  pre[1+idx:]  → 右子树前序(剩下全部)

3. 空子树

if not pre_o: return '' 必须在开头,对应叶子节点的左右空子树。

同类变体

已知条件 求目标 异同
前序 + 中序 后序 本题,根在前序首
后序 + 中序 前序 根在后序尾,其余对称
前序 + 后序 中序 不唯一(无法区分单子节点时是左还是右)

规律:必须有中序才能唯一确定二叉树结构。

时间复杂度

  • 每次 index() 扫描中序,O(n)
  • 递归 n 层,每层 O(n) → 总 O(n²)
  • 因 n ≤ 26,完全够用。大数据可预处理字符→位置的哈希表优化到 O(n)。

posted on 2026-05-18 18:12  ruye07  阅读(31)  评论(0)    收藏  举报