题解:AcWing 3598 二叉树的遍历(前序中序求后序-字符串)
【题目来源】
AcWing:3598 二叉树遍历 - AcWing题库
【题目描述】
假定一棵二叉树的每个结点都用一个大写字母描述。
给定这棵二叉树的前序遍历和中序遍历,求其后序遍历。
【输入】
输入包含多组测试数据。
每组数据占两行,每行包含一个大写字母构成的字符串,第一行表示二叉树的前序遍历,第二行表示二叉树的中序遍历。
【输出】
每组数据输出一行,一个字符串,表示二叉树的后序遍历。
【输入样例】
ABC
BAC
FDXEAG
XDEFAG
【输出样例】
BCA
XEDGAF
【核心思想】
-
问题分析:给定二叉树的先序遍历字符串 \(pre\) 和中序遍历字符串 \(ins\),每个结点用大写字母表示。需要根据这两种遍历结果重建二叉树并输出后序遍历。关键在于利用先序遍历确定根节点,利用中序遍历分割左右子树。
-
算法选择:
- 递归分治(DFS):利用先序遍历的第一个字符确定当前子树的根节点
- 中序分割:在中序遍历中找到根节点位置 \(k\),左侧为左子树,右侧为右子树
- 字符串截取:通过
substr截取子串,递归处理左右子树
-
关键步骤:
- 递归终止条件:当先序字符串 \(pre\) 为空时,返回(空子树)
- 确定根节点:先序遍历的第一个字符 \(pre[0]\) 即为当前子树的根节点 \(root\)
- 查找根位置:在中序遍历 \(ins\) 中找到根节点位置 \(k = ins.find(root)\)
- 计算左子树规模:左子树包含 \(k\) 个结点
- 递归左子树:
- 先序子串:\(pre.substr(1, k)\)(从位置1开始,长度为 \(k\))
- 中序子串:\(ins.substr(0, k)\)(从位置0开始,长度为 \(k\))
- 递归右子树:
- 先序子串:\(pre.substr(k + 1)\)(从位置 \(k+1\) 开始到末尾)
- 中序子串:\(ins.substr(k + 1)\)(从位置 \(k+1\) 开始到末尾)
- 输出根节点:后序遍历最后访问根节点,输出 \(root\)
-
时间/空间复杂度:
- 时间复杂度:\(O(n^2)\),其中 \(n\) 为字符串长度。每次递归需要在 \(ins\) 中查找根节点位置 \(O(n)\),递归深度为 \(O(n)\)(最坏情况退化为链)
- 空间复杂度:\(O(n^2)\),每次递归创建新的子串,最坏情况下空间复杂度为 \(O(n^2)\);若使用下标索引优化,可降至 \(O(n)\)
-
二叉树遍历的核心思想:
- 先序遍历:根 → 左 → 右,第一个字符必为根节点
- 中序遍历:左 → 根 → 右,根节点左侧为左子树,右侧为右子树
- 后序遍历:左 → 右 → 根,最后访问根节点
- 递归重建:通过先序确定根,通过中序分割左右,递归构建整棵树
- 适用于已知两种遍历序列求第三种遍历序列的经典问题
【解题思路】
1.样例建树过程:

2.下标k是根字符在中序位置

【算法标签】
DFS-树
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 110; // 最大字符串长度
string pre, ins; // pre: 先序遍历字符串, ins: 中序遍历字符串
/**
* 根据先序和中序遍历结果构建二叉树并输出后序遍历
* 递归算法:利用先序确定根节点,利用中序分割左右子树
* @param pre 当前子树的先序遍历字符串
* @param ins 当前子树的中序遍历字符串
*/
void porder(string pre, string ins)
{
// 递归终止条件:空子树
if (pre.empty())
return;
// 先序遍历的第一个字符是根节点
char root = pre[0];
// 在中序遍历中找到根节点的位置
int k = ins.find(root);
// 递归处理左子树:
// 左子树的先序:pre[1]到pre[k](长度为k)
// 左子树的中序:ins[0]到ins[k-1](长度为k)
porder(pre.substr(1, k), ins.substr(0, k));
// 递归处理右子树:
// 右子树的先序:pre[k+1]到末尾
// 右子树的中序:ins[k+1]到末尾
porder(pre.substr(k + 1), ins.substr(k + 1));
// 后序遍历:最后访问根节点
cout << root;
}
int main()
{
// 循环读取多组测试数据
while (cin >> pre >> ins)
{
// 根据先序和中序输出后序遍历结果
porder(pre, ins);
cout << endl;
}
return 0;
}
【运行结果】
ABC
BAC
BCA
FDXEAG
XDEFAG
XEDGAF
^Z
浙公网安备 33010602011771号