zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    ");
                print(1);
            }
            else{
                flag = true;
                cnt = 1;
                re_qianxv(1);
                if(flag){
                    printf("YES
    ");
                    reprint(1);
                }
                else{
                    printf("NO
    ");
                }
            }
        }
        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
    ");
            }
            else{
                printf("YES
    %d", tree[0]);
                for(int i = 1; i < n; i++){
                    printf(" %d", tree[i]);
                }
                cout<<endl;
            }
        }
        return 0;
    }
    


  • 相关阅读:
    2020.02.28 【ABAP随笔】- EXCEL批导程式3
    2020.02.27 【ABAP随笔】- EXCEL批导程式2
    2020.02.26 【ABAP随笔】- EXCEL批导程式1
    2020.02.24 【ABAP随笔】- EXCEL常见操作笔记 1
    2020.02.15 【ABAP随笔】- 物料主数据增强
    2020.01.14 【ABAP随笔】-程序优化笔记
    2020.01.11 【ABAP随笔】获取标准报表数据(MB52)数据进行客制ALV
    2020.01.11 【ABAP随笔】SM30常见增强操作-自动带描述等
    2020.01.10 【ABAP随笔】ALV上的下拉框
    Linux资源监控命令/工具(调试)
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9643418.html
Copyright © 2011-2022 走看看