每日一题之 hiho 1697 最小先序遍历 (二叉树遍历变形,知道中序,求字典序最小的先序)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014046022/article/details/81673449

描述
有一棵包含N个节点的二叉树,节点编号是1~N。

现在我们知道它的中序遍历结果A1, A2, … AN。

只有中序遍历显然不能确定一棵二叉树的形态,可能有很多棵不同的二叉树符合给定的中序遍历。

那么你能从中找出先序遍历结果字典序最小的二叉树吗?

设先序遍历结果是P1, P2, … PN。字典序最小指首先P1应尽量小,其次P2尽量小,再次P3尽量小…… 以此类推。

输入
第一行包含一个整数N。 (1 <= N <= 100)

以下N行每行包含一个整数Ai。 (1 <= Ai <= N)

输出
输出N行,依次是P1, P2, … PN。代表最小的先序遍历结果。

样例输入
5
5
4
1
3
2
样例输出
1
4
5
2
3

思路:

由于只知道中序序列,中序序列相同的树有很多,显然不能暴力枚举。这时候想想先序和中序的关系,先序字典序最小,先序遍历先遍历根节点,也就是根节点要最小。所以我们可以找到中序序列中的最小值,将它作为树的根节点,将中序序列分为两部分,然后递归的对这两部分按照同样的策略找根。这样构造的先序序列保证是字典序最小的。

#include <bits/stdc++.h>

using namespace std;


vector<int>A;
vector<int>res;

void solve(int l,int r)
{   
    if (l > r) return;
    if (l == r)  {
        res.push_back(A[l]);
        return;
    }
    int mid = l;
    for (int i = l; i <= r; ++i) {
        if (A[i] <= A[mid]) {
            mid = i;
        }
    }
    res.push_back(A[mid]);
    solve(l,mid-1);
    solve(mid+1,r);

}


int main()
{

    int n,x;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> x;
        A.push_back(x);
    }
    solve(0,n-1);
    for (auto x: res) {
        cout << x << endl;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/u014046022/article/details/81673449