2020北航计算机夏令营机试 T1 二叉树

题意:

  • 给你一个整数序列,用这些数构成一个完全二叉排序树,输出此二叉树的层序遍历序列。
  • 输入的第一行是一个整数n,表示这个整数序列的长度,输入的第二行包含n个整数,每个数代表完全二叉排序树的一个节点,现在需要输出由这n个整数构成的完全二叉排序树的层序遍历序列。

输入样例:

18
56 987 -25 0 1021 -238 399 12 77 -1 72190 -25 -168 -41367 3218 12 0 -25

输出样例:

12 -1 987 -25 0 77 3218 -238 -25 0 12 56 399 1021 72190 -41367 -168 -25

样例解释:

  • 输入样例对应的完全二叉排序树如下图所示:

test

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e9+7;

int n; int a[1000010];
vector<int> level[25];
int p2[30]; // 1 2 4 8 16 32

void solve(int left, int right, int level_num){
//    cout<<"left, right, level_num = "<<left<<", "<<right<<", "<<level_num<<endl;
    int cnt = right-left+1; // 18
    if(cnt <= 0) return;
    if(cnt==1){
        level[level_num].push_back(a[right]); return;
    }
    int height = lower_bound(p2, p2+30, cnt+1) - p2;
//    cout<<"height = "<<height<<endl; // 5
    int root = p2[height-1]-1; // 15
    if(cnt-root < p2[height-2]) root -= p2[height-2] - (cnt-root);
    root += left;
    level[level_num].push_back(a[root]); // 10
    solve(left, root-1, level_num+1);
    solve(root+1, right, level_num+1);
}

int main(){
    ios::sync_with_stdio(false);
    p2[0] = 1; for(int i=1; i<30; ++i) p2[i]=2*p2[i-1];

    cin>>n; for(int i=0; i<n; ++i) cin>>a[i];
    sort(a, a+n);
//    for(int i=0; i<n; ++i) cout<<a[i]<<" "; cout<<endl;

    solve(0, n-1, 0);
//    cout<<"done!\n";

    int level_num=0;
    while(1){
        if(level[level_num].empty()) break;
        for(auto leaf : level[level_num]) cout<<leaf<<" ";
        ++level_num;
    }
}


/*
完全二叉排序树。
首先得到中序遍历,然后得到层序遍历?

56 987 -25 0 1021 -238 399 12 77 -1 72190 -25 -168 -41367 3218 12 0 -25

-41367 -238 -168 -25 -25 -25 -1 0 0 12 12 56 77 399 987 1021 3218 72190

18个数,最接近的是31, 所以5 层。
最后一次是否铺满?铺了 3/16。
RHS 是否铺满?0/8。
LHS 铺了多少?3/8。所以 (7+3) - 1 - 7。然后递归?
12 -1 987 -25 0 77 3218 -238 -25 0 12 56 399 1021 72190 -41367 -168 -25

*/

posted @ 2022-07-07 08:46  MoonOut  阅读(60)  评论(0)    收藏  举报