更多PAT甲级题解--acking-you.github.io

题目

OJ平台

题目解析

题目大意:

二叉搜索树大家都不陌生,这个题需要你构造的二叉树二叉搜索树同时也是完全二叉树,然后打印出它的层序遍历序列。

  • 这道题把我坑到了,我竟第一时间想的并不是从它的中序重新构建出这颗二叉树,我开始想的非常复杂🤣

首先根据二叉搜索树的性质可知它的中序遍历序列(直接排个序),实际上知道了中序遍历序列就已经可以构造出对应的完全二叉树了,根据中序利用递归反向推导即可

然而我却第一时间想到的是先求出这颗完全二叉树的层数,然后根据这个求出这颗完全二叉树左子树的个数,然后便可以得出这颗完全二叉树的根结点(由于有序,且根结点的左边都是小于根结点的数,所以直接根据左子树结点个数可得出根节点的编号),我一心只想着求出这个总根之后再取构建完全二叉树,熟不知给你的本就是一棵完全二叉树,只需要根据中序直接构建即可!

看看我这错误代码🤣(实际数据量不大都能过

#include <bits/stdc++.h>
using namespace std;
int N;
int* nums;
int* res;
int left_sum;
void pre_handle() { //由于是完全二叉树,所以设层数为i则有,2^(i-1)-1<=N<=2^i-1
    int i = 1;
    while ((1 << i) - 1 < N)i++;
    int leave = N - (1 << (i - 1)) + 1 > (1 << (i - 1)) / 2 ? (1 << (i - 1)) / 2 : N - (1 << (i - 1)) + 1; //判断是否半满,如果大于半满则左子树的尾数为半满个数
    left_sum = leave + ((1 << (i - 1)) - 2) / 2; //得出左子树总个数
}
void Input() {
    ios::sync_with_stdio(false);
    cin >> N;
    nums = new int[N];
    res = new int[N];
    for (int i = 0; i < N; i++) {
        cin >> nums[i];
    }
    sort(nums, nums + N);
    pre_handle();
}
void BST(int root, int l, int r) {
    if (l > r)
        return ;
    int t_l = l, t_r = r, node;
    if (root == 0) {
        node = l + left_sum;
    }
    else node = (t_l + t_r) % 2 == 0 ? (t_l + t_r) / 2 : (t_l + t_r) / 2 + 1;
    res[root] = nums[node];
    BST(root * 2 + 1, l, node - 1);
    BST(root * 2 + 2, node + 1, r);
}
void print() {
    BST(0, 0, N - 1);
    for (int i = 0; i < N; i++) {
        if (i != N - 1)
            cout << res[i] << ' ';
        else
        {
            cout << res[i];
        }

    }
}
int main() {
    Input();
    print();
    return 0;
}

正确代码详解

实际上我们只要对中序遍历理解的够深,基本就能秒了。

由于我们经过排序后的数据就是中序遍历,而中序遍历都是 左-根-右 ,所以在我们重新构建完全二叉树的时候也需要是 左-根-右 ,对于从数组下标0开始的完全二叉树,有左子树为 i*2+1 ,右子树为 i*2+2 。由于子树都是抽象的数据,根则是具体的,所以需要不断递归直到得到根就开始给完全二叉树赋值。

  • 由于用数组存下完全二叉树的序列后,它的序列就是层序遍历的序列。。。所以直接打印即可
#include <bits/stdc++.h>
using namespace std;
int N;
int* nums;
int* res;
int idx = 0;
void Input() {
    ios::sync_with_stdio(false);
    cin >> N;
    nums = new int[N];
    res = new int[N];
    for (int i = 0; i < N; i++) {
        cin >> nums[i];
    }
    sort(nums, nums + N);
}
void creatCBT(int root) {
    if (root >= N) return;
    creatCBT(root * 2 + 1); //左子树
    res[root] = nums[idx++];//根
    creatCBT(root * 2 + 2); //右子树
}
void print() {
    creatCBT(0);
    for (int i = 0; i < N; i++) {
        cout << res[i] << ' ';
    }
}
int main() {
    Input();
    print();
    return 0;
}