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() ? '\n' : ' ');
        }
    }
    return 0;
}

 

posted on 2017-12-20 21:44  ZefengYao  阅读(228)  评论(0编辑  收藏  举报

导航