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

    思路:搜索二叉树的重建,告诉你了前序遍历,那么可以进行递归的找出后序遍历。前序遍历的特性可知,每次递归的查找区间[l,r]的根以及其左右子树,节点l处的值一定是根,因为前序遍历总是先确定出根,之后再去搜索其左子树和右子树。
    那么左子树和右子树的范围应当如何确定呢?首先左右子树当中所有的元素的编号应当在[l+1,r]中,并且由搜索树的性质,在根的左子树上的值都小于根,右子树上的值大于等于根,那么容易确定出左右子树了。
    之后模拟后续遍历:即先递归搜素左右子树,之后再输出当前节点处的值。
    AC代码:
    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #include<cstring> 
    #include<string>
    #include<queue>
    #include<cmath>
    #include<map>
    #include<set>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define EPS 1e-5
    #define pi cos(-1)
    const int N_MAX = 1000+ 15;
    int n,pos;
    bool is_mirror;
    vector<int>pre,post;
    void dfs(const int& l, const int& r) {//找出[l,r]区间范围的根以及其左右子树
            if (l > r)return;
            int root = pre[pos++];
            int i = l + 1, j = r;
            if (!is_mirror) {//不是镜像,左子树上的值要比root小,右子树上的值大于等于root
                while (i <= r&&root>pre[i])i++;
                while (j>l&&root <= pre[j])j--;
            }
            else {
                while (i <= r&&root <= pre[i])i++;
                while (j >l&&root> pre[j])j--;
            }
            if (i - j != 1)return;//如果不是搜索树不满足条件
    
            dfs(l + 1, j);
            dfs(i, r);
    
            post.push_back(root);
        }
    
    
    int main() {
        scanf("%d", &n);
            pre.resize(n);
            for (int i = 0; i < n;i++) {
                scanf("%d",&pre[i]);
            }
            pos = 0;
            is_mirror = 0;
            dfs(0, n-1);
            if (post.size()!=n) {
                pos = 0;
                post.clear();
                is_mirror = 1;
                dfs(0, n-1);
            }
            if (post.size() == n) {
                puts("YES");
                for (int i = 0; i <n;i++) {
                    cout << post[i];
                    if (i + 1 == n)cout << endl;
                    else cout << " ";
                }
                
            }
            else {
                puts("NO");
            }
            pre.clear();
        
        return 0;
    }

     如果知道后序遍历,让你判断是否是搜索树,如果是,输出前序遍历,方法也类似,贴一下代码:

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<string>
    #include<iomanip>
    #include<map>
    #include<stack>
    #include<set>
    #include<queue>
    #include<sstream>
    using namespace std;
    #define N_MAX 100000+2
    #define INF 0x3f3f3f3f
    struct Node {
        int key=INF, left, right;
        Node() {}
        Node(int key,int left,int right):key(key),left(left),right(right) {}
    }node[N_MAX];
    int n,cnt=n-1;
    vector<int>pre,post;
    bool ok = 1;
    void dfs(int n, int l, int r, bool is_mirror) {
        if (l > r)return;
        int root = post[cnt--];
        int i = l, j = r-1;
        if (!is_mirror) {
            while (i < r&&post[i] <root) i++;
            while (j >= l&&post[j] >= root)j--;
        }
        else {
            while (i < r&&post[i] >= root) i++;
            while (j >= l&&post[j] < root)j--;
        }
        if (i - j != 1) {
            ok = 0; return;
        }
        node[n] = Node(root, 2 * n + 1, 2 * n + 2);
        dfs(2*n+2,i, r-1,is_mirror);
        dfs(2*n+1,l, j,is_mirror);//!!!
    }
    
    
    void preorder(int n) {
        pre.push_back(node[n].key);
        if (node[2*n+1].key != INF)preorder(node[n].left);
        if (node[2*n+2].key != INF)preorder(node[n].right);
    }
    
    int main() {
        while (cin >> n) {
            post.resize(n);
            for (int i = 0; i < n; i++)cin >> post[i];
            ok = 1; cnt = n-1;
            dfs(0,0, n - 1, 0);
            if (!ok) {
                ok = 1; cnt = n-1;
                dfs(0,0, n - 1, 1);
                if (!ok) {
                    puts("NO");
                }
            }
            if (ok) {
                preorder(0);
                puts("YES");
                for (int i = 0; i < pre.size(); i++)
                    printf("%d%c", pre[i], i + 1 == pre.size() ? '
    ' : ' ');
            }
        }
        return 0;
    }
  • 相关阅读:
    【代码笔记】iOS-判断是否是模拟机
    【代码笔记】iOS-拍照动画
    【代码笔记】iOS-轮询弹出框
    【代码笔记】iOS-iCarouselDemo
    【代码笔记】iOS-UIScrollerView里有两个tableView
    【代码笔记】iOS-两个时间字符串的比较
    【代码笔记】iOS-利用图片序列创建动态图片效果
    【代码笔记】iOS-离线地图
    【代码笔记】iOS-看图听声音
    【代码笔记】iOS-看图听故事
  • 原文地址:https://www.cnblogs.com/ZefengYao/p/8075984.html
Copyright © 2011-2022 走看看