PAT天梯赛L2-004 这是二叉搜索树吗【递归】

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

时间限制
400 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越

一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,

  • 其左子树中所有结点的键值小于该结点的键值;
  • 其右子树中所有结点的键值大于等于该结点的键值;
  • 其左右子树都是二叉搜索树。

所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。

给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。

输入格式:

输入的第一行给出正整数N(<=1000)。随后一行给出N个整数键值,其间以空格分隔。

输出格式:

如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出“YES”,然后在下一行输出该树后序遍历的结果。数字间有1个空格,一行的首尾不得有多余空格。若答案是否,则输出“NO”。

输入样例1:
7
8 6 5 7 10 8 11
输出样例1:
YES
5 7 6 8 11 10 8
输入样例2:
7
8 10 11 8 6 7 5
输出样例2:
YES
11 8 10 7 5 6 8
输入样例3:
7
8 6 8 5 10 9 11
输出样例3:
NO
emmm感觉数据结构好像学了都忘掉了

关于二叉树怎么建怎么遍历不是很熟悉了

算是很好的一道复习的题目

递归建树 递归遍历

然而还是看了题解


第一个思路是先建树 然后对这个树前序遍历 和原来的数组比较

然后再后序遍历树  

有一组段错误 应该是runtime error  

大概是递归太多爆栈了?

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
#include<cstring>
#include<queue>
#include<stack>
#define inf 0x3f3f3f3f

using namespace std;

int n;
int vis[10005];
int tree[10005];
int num[10005];

void build(int rt, int x)
{
    if(!vis[rt]){
        vis[rt] = true;
        tree[rt] = x;
        return ;
    }

    if(x >= tree[rt]){
        build(2 * rt + 1, x);
    }
    else{
        build(2 * rt, x);
    }
}

bool flag;
int cnt;
void qianxv(int k)
{
    if(flag == 0)return ;
    if(tree[k] == num[cnt]){
        cnt++;
        if(vis[2 * k]) qianxv(2 * k);
        if(vis[2 * k + 1]) qianxv(2 * k + 1);
    }
    else
        flag = 0;
    return;
}

void re_qianxv(int k)
{
    if(flag == 0) return ;
    if(tree[k] == num[cnt]){
        cnt++;
        if(vis[2 * k + 1])re_qianxv(2 * k + 1);
        if(vis[2 * k])re_qianxv(2 * k);
    }
    else flag = 0;
    return ;
}

void print(int k)
{
    if(vis[2 * k])print(2 * k);
    if(vis[2 * k + 1]) print(2 * k + 1);
    if(k == 1){
        printf("%d\n", tree[k]);
    }
    else{
        printf("%d ", tree[k]);
    }
    return;
}

void reprint(int k)
{
    if(vis[2 * k + 1])reprint(2 * k + 1);
    if(vis[2 * k])reprint(2 * k);
    if(k == 1){
        printf("%d\n", tree[k]);
    }
    else{
        printf("%d ", tree[k]);
    }
    return;
}

int main()
{
    while(cin>>n){
        memset(vis, 0, sizeof(vis));
        for(int i = 1; i <= n; i++){
            cin>>num[i];
            build(1, num[i]);
        }
        flag = true;
        cnt = 1;
        qianxv(1);
        if(flag){
            printf("YES\n");
            print(1);
        }
        else{
            flag = true;
            cnt = 1;
            re_qianxv(1);
            if(flag){
                printf("YES\n");
                reprint(1);
            }
            else{
                printf("NO\n");
            }
        }
    }
    return 0;
}


第二个思路是区间递归 

前序的话根节点肯定在前面 然后后面跟了一段都比他小 在后面跟了一段都比他大 找到那个分界点

类似于快排的partition?

如果找到那个点 两段中间还差一大段说明这个不是前序遍历的

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
#include<cstring>
#include<queue>
#include<stack>
#define inf 0x3f3f3f3f

using namespace std;

int n;
int num[1005];
bool isMirror;
vector<int>tree;

void f(int l, int r)
{
    if(l > r) return;

    int tr = l + 1;//tr - r是右子树
    int tl = r;//l + 1 - tl是左子树

    if(!isMirror){
        while(tr <= r && num[tr] < num[l]) tr++;
        while(tl > l && num[tl] >= num[l]) tl--;
    }
    else{
        while(tr <= r && num[tr] >= num[l]) tr++;
        while(tl > l && num[tl] < num[l]) tl--;
    }

    if(tr - tl != 1) return;
    f(l + 1, tl);
    f(tr, r);
    tree.push_back(num[l]);
}

int main()
{
    while(cin>>n){
        tree.clear();
        for(int i = 0; i < n; i++){
            cin>>num[i];
        }
        isMirror = 0;
        f(0, n - 1);
        if(tree.size() != n){
            isMirror = 1;
            tree.clear();
            f(0, n - 1);
        }

        if(tree.size() != n){
            printf("NO\n");
        }
        else{
            printf("YES\n%d", tree[0]);
            for(int i = 1; i < n; i++){
                printf(" %d", tree[i]);
            }
            cout<<endl;
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/wybooooooooo/article/details/79754200