L2-004 这是二叉搜索树吗?

L2-004 这是二叉搜索树吗? ,第1张

原题链接https://pintia.cn/problem-sets/994805046380707840/problems/994805070971912192

分析

本题主要考察了二叉搜索树(二叉排序树)的性质:

  1. 二叉排序树的左子树全部小于根节点,右子树全部大于等于根节点,同理,二叉排序树的每个非叶子结点都满足

    T:在判断所给序列是否是前序序列时就用这个性质判断,因为前序是先根再左再右,所以每个二叉排序树的前序遍历数组(1~n)都会满足:从第二个位置开始都比第一个位置(根节点)小,直到遇到第一个比根节点大的,后面都必须都比根节点大
  2. 二叉排序树的中序遍历就是所有结点的值从小到大的排列,即将前序遍历的结果按从小到大排序就是中序遍历

    T:利用这个性质,得到树的前中后序,就可以生成它的后序了

注意:对于镜像,大小判断的标准反过来就行,同时镜像的前序,左右子树的位置互换了,所以要从后面开始往前遍历。


因为本人写的代码太过繁琐,借鉴了网上的一篇思路非常清晰的代码,做了详细的注释供大家参考

代码
#include 
using namespace std;

const int N = 1e3 + 5;
int pre[N], in[N], post[N], idx;
int n;

//判断是不是前序
bool isPre(int a[], int left, int right)
{
    //如果只有一个节点了自然是正确的返回true
    if (left >= right)
        return true;
    int i = left + 1, j;
    //从左往右遍历,二叉搜索树(二叉排序树)的左子树是小于根节点的
    while (i <= right && a[i] < a[left])
        i++;
    j = i; //得到左右子树的分界线
    //继续往后遍历,此时是根节点的右子树,都要大于等于根节点
    while (i <= right && a[i] >= a[left])
        i++;
    //如果i没要到right+1,说明至少有一个点是违背了二叉搜索树的规则导致提前退出循环,所以返回false
    if (i <= right)
        return false;

    //再去分别判断左右子树是否满足
    bool l = isPre(a, left + 1, j - 1);
    bool r = isPre(a, j, right);

    return l && r;
}

//判断是不是镜像
bool isMirror(int a[], int left, int right)
{
    if (left >= right)
        return true;
    int i = left + 1, j;

    while (i <= right && a[i] >= a[left])
        i++;
    j = i;
    while (i <= right && a[i] < a[left])
        i++;

    if (i <= right)
        return false;

    bool l = isMirror(a, left + 1, j - 1);
    bool r = isMirror(a, j, right);

    return l && r;
}

void getPost(int pre[], int in[], int len)
{
    if (len <= 0)
        return;
    int i;
    for (i = 0; i < len; i++)
        if (in[i] == pre[0])
            break;

    getPost(pre + 1, in, i);
    getPost(pre + i + 1, in + i + 1, len - i - 1);
    post[idx++] = pre[0];
}

void getPost_Mirror(int pre[], int in[], int len)
{
    if (len <= 0)
        return;
    int i;
    //镜像的前序,左右子树的位置互换了,所以要从后面开始往前遍历
    for (i = len - 1; i >= 0; i--)
        if (in[i] == pre[0])
            break;

    getPost(pre + 1, in, i);
    getPost(pre + i + 1, in + i + 1, len - i - 1);
    post[idx++] = pre[0];
}
bool cmp(int a, int b)
{
    return a > b;
}

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

    if (isPre(pre, 1, n))
    {
        cout << "YES" << '\n';
        //对于二叉搜索树(二叉排序树)的中序遍历就是树的所有结点从小到大的排列
        //对前序序列进行排序得到的就是中序序列
        sort(in + 1, in + 1 + n);
        getPost(pre + 1, in + 1, n);
        cout << post[0];
        for (int i = 1; i < n; i++)
            cout << " " << post[i];
    }
    else if (isMirror(pre, 1, n))
    {
        cout << "YES" << '\n';
        sort(in + 1, in + 1 + n, cmp);
        getPost_Mirror(pre + 1, in + 1, n);
        cout << post[0];
        for (int i = 1; i < n; i++)
            cout << " " << post[i];
    }
    else
        cout << "NO";

    return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/564981.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-06
下一篇 2022-04-06

发表评论

登录后才能评论

评论列表(0条)

保存