数据结构不难11

2019/3/22更新

后序遍历

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

<dl class="des">

描述

在参与过了美食节之后,小Hi和小Ho在别的地方又玩耍了一阵子,在这个过程中,小Ho得到了一个非常有意思的玩具——一棵由小球和木棍连接起来的二叉树

小Ho对这棵二叉树爱不释手,于是给它的每一个节点都标记了一个标号——一个属于A..Z的大写字母,并且没有任意两个节点的标号是一样的。小Hi也瞅准了这个机会,重新巩固了一下小Ho关于二叉树遍历的基础知识~就这样,日子安稳的过了两天。

这天,小Ho正好在求解这棵二叉树的前序、中序和后序遍历的结果,但是却在求出前序遍历和中序遍历之后不小心把二叉树摔到了地上,小球和木棍等零件散落了一地!

小Ho损失了心爱的玩具,正要嚎啕大哭起来,所幸被小Hi发现了,劝说道:“别着急,这不是零件都还在么?拼起来不就是了?”

“可是我忘记了二叉树长什么样子了!”小Ho沮丧道。

“这个简单,你不是刚刚求出了这棵二叉树的前序和中序遍历的结果么,利用这两个信息就可以还原出整棵二叉树来哦!”

“这样么?!!”小Ho止住了泪水,问道:“那要怎么做呢?”

没错!小Ho在这一周遇到的问题便是:给出一棵二叉树的前序和中序遍历的结果,还原这棵二叉树并输出其后序遍历的结果。

提示:分而治之——化大为小,化小为无

输入

每个测试点(输入文件)有且仅有一组测试数据。

每组测试数据的第一行为一个由大写英文字母组成的字符串,表示该二叉树的前序遍历的结果。

每组测试数据的第二行为一个由大写英文字母组成的字符串,表示该二叉树的中序遍历的结果。

对于100%的数据,满足二叉树的节点数小于等于26。

输出

对于每组测试数据,输出一个由大写英文字母组成的字符串,表示还原出的二叉树的后序遍历的结果。

样例输入

AB
BA

样例输出

BA

AC代码

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<memory>
#include<cstring>
using namespace std;
char p[30],m[30];
int vis[30],Len;
void _find(int L,int R)
{
    int i,j,pos=0;
    for(i=1;i<=Len&&!pos;i++) 
     for(j=L;j<=R&&!pos;j++)
      if(p[i]==m[j]) {
            pos=j;
            break;
     }
      
    if(L<pos) _find(L,pos-1);
    if(R>pos) _find(pos+1,R);
    cout<<m[pos];    
    
}
int main()
{
    int i,j;
    scanf("%s",p+1);
    scanf("%s",m+1);
    Len=strlen(p+1);
    _find(1,Len);
    return 0;
}

第二题 最近公共祖先

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

<dl class="des">

描述

小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在其中,但这是为什么呢?

“为什么呢?”小Hi如是问道,在他的观察中小Ho已经沉迷这个网站一周之久了,甚至连他心爱的树玩具都弃置一边。

“嘿嘿,小Hi,你快过来看!”小Ho招呼道。

“你看,在这个对话框里输入我的名字,在另一个对话框里,输入你的名字,再点这个查询按钮,就可以查出来……什么!我们居然有同一个祖祖祖祖祖爷爷?”

“诶,真是诶……这个网站有点厉害啊。”小Hi不由感叹道。

“是啊,这是什么算法啊,这么厉害!”小Ho也附和道。

“别2,我说的是他能弄到这些数据很厉害,而人类的繁殖树这种层数比较浅的树对这类算法的要求可是简单的不得了,你都能写出来呢!”小Hi道。

“啊?我也能写出来?可是……该从哪开始呢?”小Ho困惑了。

小Ho要面临的问题是这样的,假设现在他知道了N个人的信息——他们的父亲是谁,他需要对于小Hi的每一次提问——两个人的名字,告诉小Hi这两个人的是否存在同一个祖先,如果存在,那么他们的所有共同祖先中辈分最低的一个是谁?

提示:不着急,慢慢来,另外我有一个问题:挖掘机技术哪家强?!

输入

每个测试点(输入文件)有且仅有一组测试数据。

每组测试数据的第1行为一个整数N,意义如前文所述。

每组测试数据的第2~N+1行,每行分别描述一对父子关系,其中第i+1行为两个由大小写字母组成的字符串Father_i, Son_i,分别表示父亲的名字和儿子的名字。

每组测试数据的第N+2行为一个整数M,表示小Hi总共询问的次数。

每组测试数据的第N+3~N+M+2行,每行分别描述一个询问,其中第N+i+2行为两个由大小写字母组成的字符串Name1_i, Name2_i,分别表示小Hi询问中的两个名字。

对于100%的数据,满足N<=102,M<=102, 且数据中所有涉及的人物中不存在两个名字相同的人(即姓名唯一的确定了一个人)。

输出

对于每组测试数据,对于每个小Hi的询问,输出一行,表示查询的结果:如果根据已知信息,可以判定询问中的两个人存在共同的祖先,则输出他们的所有共同祖先中辈分最低的一个人的名字,否则输出-1。

样例输入

11
JiaYan JiaDaihua
JiaDaihua JiaFu
JiaDaihua JiaJing
JiaJing JiaZhen
JiaZhen JiaRong
JiaYuan JiaDaishan
JiaDaishan JiaShe
JiaDaishan JiaZheng
JiaShe JiaLian
JiaZheng JiaZhu
JiaZheng JiaBaoyu
3
JiaBaoyu JiaLian
JiaBaoyu JiaZheng
JiaBaoyu LinDaiyu

样例输出

JiaDaishan
JiaZheng
-1

AC代码 ---java实现

import java.util.HashMap;
import java.util.Scanner;

public class Main {

    private HashMap<String,Integer>nodeMap;
    private Node[]nodes;
    private int index;
    private int ancestorIndex;
    
    public Main(){
        this.nodeMap=new HashMap<String,Integer>();
        this.nodes=new Node[1001];
        this.index=0;
        this.ancestorIndex=-1;
    }
    
    private void reset(){
        for(int i=0;i<this.index;i++){
            this.nodes[i].isVisited=false;
        }
        this.ancestorIndex=-1;
    }
    
    private int getNode(String nodeName){        
        if(!this.nodeMap.containsKey(nodeName)){
            this.nodes[this.index]=new Node(nodeName);
            this.nodeMap.put(nodeName, this.index);
            this.index++;
        }
        return this.nodeMap.get(nodeName);
    }
    
    private void visit(int nodeIndex){
        if(nodeIndex>=0&&nodeIndex<this.index){
            if(this.nodes[nodeIndex].isVisited){
                this.ancestorIndex= nodeIndex;
                return;
            }else{
                this.nodes[nodeIndex].isVisited=true;
                int parentIndex=this.nodes[nodeIndex].parentIndex;
                this.visit(parentIndex);
            }            
        }
    }
    
    public void addNode(String parent,String child){
        int parentIndex=this.getNode(parent);
        int childIndex=this.getNode(child);
        if(parentIndex>=0&&parentIndex<this.index
                &&childIndex>=0&&childIndex<this.index){
            this.nodes[childIndex].parentIndex=parentIndex;
        }
    }
    
    public void getAncestor(String first,String second){
        int firstIndex=this.getNode(first);
        int secondIndex=this.getNode(second);
        this.visit(firstIndex);
        this.visit(secondIndex);
        if(this.ancestorIndex>=0&&this.ancestorIndex<this.index){
            this.nodes[this.ancestorIndex].print();
        }else{
            System.out.println("-1");
        }
        this.reset();
    }
    
    public static void main(String[] args) {
        
        Scanner scanner=new Scanner(System.in);
        Main ancestor=new Main();
        int n=scanner.nextInt();
        for(int i=0;i<n;i++){
            String first=scanner.next();
            String second=scanner.next();
            ancestor.addNode(first, second);
        }
        int m=scanner.nextInt();
        for(int i=0;i<m;i++){
            String first=scanner.next();
            String second=scanner.next();
            ancestor.getAncestor(first, second);
        }
    }

}

class Node{
    public String name;
    public int parentIndex;
    public boolean isVisited;
    public Node(String name){
        this.name=name;
        this.parentIndex=-1;
        this.isVisited=false;
    }
    public void print(){
        System.out.println(this.name);
    }
}

无根树变有根树

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

<dl class="des">

描述

给定一棵包含 <var>N</var> 个节点的无根树,小Hi想知道如果指定其中某个节点 <var>K</var> 为根,那么每个节点的父节点是谁?

15013494395080.png

输入

第一行包含一个整数 N 和 K。1 ≤ N ≤ 1000, 1 ≤ K ≤ N。

以下N-1行每行包含两个整数 a 和 b,代表ab之间存在一条边。 1 ≤ a, b ≤ N。

输入保证是一棵树。
输出

输出一行包含 N 个整数,分别代表1~N的父节点的编号。对于 K 的父节点输出0。
样例输入

5 4  
1 2  
3 1  
4 3  
5 1

样例输出

3 1 4 0 1

AC代码

#include <iostream>
#include <vector>
using namespace std;

const int MAXN = 1005;
int n, p[MAXN];
vector<int> G[MAXN];

void dfs(int u, int fa) {   //递归转化为以u为根的子树,u的父亲为fa
    int d = G[u].size();        //节点u的相邻点的个数
    for(int i = 0; i < d; ++i) {    //循环遍历跟这个节点相连接的d个节点。
        int v = G[u][i];       //节点u的第i个相邻点v
        if(fa != v) dfs(v, p[v] = u);  //把v的父亲节点设为u,然后递归转化为以v为根的子树
        //一定要判断v是否和其父亲节点相等!
    }
}

int main() {
    int root;
    //cin >> root;
    cin >> n>>root;
    for(int i = 1; i <= n-1; i++) {   //输入n-1条边
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
      //指定根节点。
    p[root] = 0;   //设定根节点的父亲节点为-1,代表根节点没有父亲节点。
    dfs(root, 0);
    for(int i = 1; i <= n; ++i) {
        cout << p[i] <<" ";
    }
    return 0;
}

是二叉搜索树吗

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

二叉搜索树指一棵空树或者具有下列性质的二叉树:

  1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;

  2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;

  3. 任意节点的左、右子树也分别为二叉查找树;

  4. 没有键值相等的节点。

已知现在有N个节点,键值恰好为1~N;同时给定N-1对节点的父子关系,请你判断这些节点是否构成一棵二叉搜索树。

如果不构成二叉搜索树,请输出错误代码:

错误代码1: N个节点不构成树;

错误代码2: N个节点不构成二叉树;

错误代码3: N个节点不构成二叉搜索树。

由于以上错误具有包含关系,所以你只需输出最小的错误代码。

如果构成二叉搜索树,请将这棵二叉搜索树依照一下格式序列化输出:

二叉搜索树T的序列化表示S(T):

  1. T是空树,S(T) = ()

  2. 否则设R是T的根, S(T) = (RS(T的左子树)S(T的右子树))

例如:

2
/
1 3

(2(1()())(3()()))

1

2
(1()(2()()))

输入

输入包含多组数据。

第一行包含一个整数T,代表数据组数。(1 ≤ T ≤ 10)

对于每组数据,第一行包含一个整数N,表示节点个数。 (1 ≤ N ≤ 10000)

以下N-1行,每行包含两个整数a和b,代表键值a的节点是键值b的节点的父亲。 (1 ≤ a, b ≤ N)
输出

对于每组数据,如果不构成二叉搜索树,输出ERRORX,其中X是错误代码。否则输出序列化表示。
样例输入

4  
3  
1 2  
3 2  
4  
1 2  
1 3  
1 4  
3  
1 2  
1 3  
3
2 1  
2 3

样例输出

ERROR1  
ERROR2  
ERROR3  
(2(1()())(3()()))

AC代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int M = 1e4 + 10;
vector<int> vc[M];
int fa[M] , ch[M][2] , f[M] , n , emmm , num[M];
void init() {
    for(int i = 1 ; i <= n ; i++) {
        f[i] = i;
        vc[i].clear();
    }
}
int find(int x) {
    if(x == f[x]) return f[x];
    return f[x] = find(f[x]);
}
int cnt;
void cau(int u) {
    int len = vc[u].size();
    if(len == 2) {
        if(vc[u][0] == vc[u][1] || vc[u][0] == u || vc[u][1] == u) emmm = 1;
        cau(vc[u][0]);
        num[cnt++] = u;
        cau(vc[u][1]);
    }
    if(len == 1) {
        if(vc[u][0] == u) emmm = 1;
        if(vc[u][0] > u) {
            num[cnt++] = u;
            cau(vc[u][0]);
        }
        else {
            cau(vc[u][0]);
            num[cnt++] = u;
        }
    }
    if(len == 0) {
        num[cnt++] = u;
    }
}
void dfs(int u) {
    int len = vc[u].size();
    if(len == 1) {
        if(u > vc[u][0]) {
            putchar('(');
            printf("%d" , vc[u][0]);
            dfs(vc[u][0]);
            putchar(')');
            putchar('(');
            putchar(')');
        }
        else {
            putchar('(');
            putchar(')');
            putchar('(');
            printf("%d" , vc[u][0]);
            dfs(vc[u][0]);
            putchar(')');
        }
    }
    if(len == 2) {
        putchar('(');
        printf("%d" , vc[u][0]);
        dfs(vc[u][0]);
        putchar(')');
        putchar('(');
        printf("%d" , vc[u][1]);
        dfs(vc[u][1]);
        putchar(')');
    }
    if(len == 0) {
        putchar('(');
        putchar(')');
        putchar('(');
        putchar(')');
    }
}
int main() {
    int t;
    scanf("%d" , &t);
    while(t--) {
        cnt = 0;
        scanf("%d" , &n);
        memset(fa , -1 , sizeof(fa));
        int flag = 0;
        init();
        for(int i = 1 ; i <= n - 1 ; i++) {
            int u , v;
            scanf("%d%d" , &u , &v);
            vc[u].push_back(v);
            int a = find(u) , b = find(v);
            if(a == b) {
                flag = 1;
            }
            else {
                f[b] = a;
            }
            if(fa[v] == -1) {
                fa[v] = u;
                continue;
            }
            else {
                flag = 1;
            }
        }
        if(flag) {
            printf("ERROR1\n");
        }
        else {
            int tmp = 0;
            for(int i = 1 ; i <= n ; i++) {
                if(vc[i].size() == 0) continue;
                sort(vc[i].begin() , vc[i].end());
                if(vc[i].size() > 2) {
                    tmp = 1;
                    break;
                }
            }
            if(tmp) {
                printf("ERROR2\n");
            }
            else {
                emmm = 0;
                int root = 1;
                for(int i = 1 ; i <= n ; i++) {
                    if(fa[i] == -1) {
                        root = i;
                        break;
                    }
                }
                cau(root);
                for(int i = 1 ; i < cnt ; i++) {
                    if(num[i] <= num[i - 1]) {
                        emmm = 1;
                        break;
                    }
                }
                if(emmm) {
                    printf("ERROR3\n");
                }
                else {
                    putchar('(');
                    printf("%d" , root);
                    dfs(root);
                    putchar(')');
                    puts("");
                }
            }
            
        }
    }
    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容