根据前序遍历和中序遍历恢复原二叉树

前序遍历的第一个元素是根,设其为r,则可以在中序遍历中找到r,并分别确定左右子树的前序遍历和中序遍历。这样递归求解即可。

注意,在中序遍历中查找r时,可以不用遍历,而是预处理出每个r在中序遍历I中的位置invI,这样就可以在O(1)的时间查找到。

是否可以生成一棵二叉树的条件为,每一次递归,判断r在中序遍历中的位置,是否在当前中序遍历数组的范围内即可。

例题:

F - Pre-order and In-order

https://atcoder.jp/contests/abc255/tasks/abc255_f

参考代码

官方:返回值为当前范围的序列是否可以生成二叉树,在序列中直接获取左右子树

复制代码
#include <iostream>
using namespace std;

int n;
int P[200005], I[200005], Iinv[200005];
int L[200005], R[200005];

bool solve(int s, int t, int S, int T)
{
  int r = P[s], p = Iinv[r];
  if(p < S || T < p) return false;

  if(p-S > 0){
    L[r] = P[s+1];
    if(!solve(s+1, s+p-S, S, p-1)) return false;
  }
  if(T-p > 0){
    R[r] = P[s+p-S+1];
    if(!solve(s+p-S+1, t, p+1, T)) return false;
  }
  return true;
}

int main(void)
{
  cin >> n;
  for(int i = 1; i <= n; i++) cin >> P[i];
  for(int i = 1; i <= n; i++) cin >> I[i];
  for(int i = 1; i <= n; i++) Iinv[I[i]] = i;

  if(P[1] != 1 || !solve(1, n, 1, n)){
    cout << -1 << endl;
    return 0;
  }
  for(int i = 1; i <= n; i++) cout << L[i] << " " << R[i] << endl;

  return 0;
}
View Code
复制代码

 

自写:返回值为根节点标号,递归用返回值获取左右子树,用全局flag记录是否可以生成二叉树

复制代码
#include<bits/stdc++.h>
using namespace std;

typedef long long LL;

int l[200010];
int r[200010];
int pre[200010];
int in[200010];
int val_to_index[200010];
int n;
bool flag = true;
int dfs(int l1, int r1, int l2, int r2)
{
    if (!flag)
        return -1;
    if (r1 < l1)
        return 0;
    if (r1 == l1)
    {

        l[pre[l1]] = 0;
        r[pre[l1]] = 0;
        return pre[l1];
    }

    int root = pre[l1];

    int index = val_to_index[root];

    if (index<l2||index>r2)
    {
        flag = false;
        return -1;
    }
    l[root] = dfs(l1 + 1, l1 + index - l2, l2, index - 1);
    if (!flag)
        return -1;
    r[root] = dfs(l1 + index - l2 + 1, r1, index + 1, r2);
    if (!flag)
        return -1;


    return root;
}
void YD()
{

    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> pre[i];
    for (int i = 1; i <= n; i++)
    {
        cin >> in[i];
        val_to_index[in[i]] = i;
    }

    dfs(1, n, 1, n);


    if (!flag||pre[1]!=1)
    {
        cout << -1 << endl;
        return;
    }

    for (int i = 1; i <= n; i++)
    {
        cout << l[i] << ' ' << r[i] << endl;
    }

}
int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T--)
    {
        YD();
    }
}
View Code
复制代码

 

posted @   80k  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示