【ACWing】1259. 二叉树遍历

题目地址:

https://www.acwing.com/problem/content/description/1261/

树和二叉树基本上都有先序、中序、后序、按层遍历等遍历顺序,给定中序和其它一种遍历的序列就可以确定一棵二叉树的结构。假定一棵二叉树一个结点用一个字符描述,现在给出中序和按层遍历的字符串,求该树的先序遍历字符串。

输入格式:
两行,每行是由大写字母组成的字符串(一行的每个字符都是唯一的),分别表示二叉树的中序遍历和按层遍历的序列。

输出格式:
一行,表示二叉树的先序序列。

数据范围:
输入字符串的长度均不超过 26 26 26

给定层序遍历 t t t之后,首先知道 t [ 0 ] t[0] t[0]是树根,我们可以根据层序遍历来把整棵树构造出来。在遍历 t t t的时候构造整棵树,缺乏的是不知道当前遍历到的节点是左孩子还是右孩子,这个时候中序遍历就起到了作用,我们只需要看当前节点在中序遍历的位置,如果这个位置左边还有没遍历过的元素,则说明当前节点是左孩子,否则是右孩子。同时需要在中序遍历中标记一下当前节点用过了。构造完整棵树之后再前序遍历一遍即可。代码如下:

#include <iostream>
#include <cstring>
#include <queue>
#include <unordered_map>
using namespace std;

const int N = 50;
int l[N], r[N], idx;
string sin, slevel;
unordered_map<char, int> mp;
bool vis[N];

void dfs(int u) {
  if (~u) {
    cout << slevel[u];
    dfs(l[u]);
    dfs(r[u]);
  }
}

int main() {
  memset(l, -1, sizeof l);
  memset(r, -1, sizeof r);
  cin >> sin >> slevel;
  for (int i = 0; i < sin.size(); i++) mp[sin[i]] = i;
  queue<int> q;
  q.push(0);
  while (q.size()) {
    int t = q.front(); q.pop();
    int k = mp[slevel[t]];
    vis[k] = true;
    // 判断++idx是不是左孩子
    if (k && !vis[k - 1]) {
      l[t] = ++idx;
      q.push(idx);
    }
    // 判断++idx是不是右孩子
    if (k < sin.size() - 1 && !vis[k + 1]) {
      r[t] = ++idx;
      q.push(idx);
    }
  }

  dfs(0);
}

时空复杂度 O ( n ) O(n) O(n) n n n为字符串长度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值