洛谷 P1030 [NOIP2001 普及组] 求先序排列

本文探讨了如何利用中序遍历和后序遍历构建前序遍历的递归算法,通过实例和代码展示了如何正确处理边界条件,以及如何利用递归进行树形结构的遍历。重点介绍了两个代码实现,并分析了孤儿节点在中序与前序序列中的影响。
摘要由CSDN通过智能技术生成

原题传送门;[NOIP2001 普及组] 求先序排列 - 洛谷


根在中序遍历的位置,左半边都是它的左子树,右半边都是它的右子树。

也就是说现在可以写出这个东西了

蒟蒻代码1号

#include <bits/stdc++.h>
using namespace std;

void travel(string mid,string back){
    char root=back[back.length()-1];
    int k=mid.find(root);
    //左子树
    travel(mid.substr(0,k));
    //右子树
    travel(mid.substr(k+1));
}

int main(){
    string mid,back;
    cin>>mid>>back;
    travel(mid,back);
    return 0;
}

因为输出的是back的最后一个,所以递归子树的back序列的最后一个要是子树的根,并且这个区间里面只能是子树的根集。

因为是递归产生的所以递归回去是正确的,不做证明。

画图即可找出对应区间。

蒟蒻代码2号(MLE)

#include <bits/stdc++.h>
using namespace std;

void travel(string mid,string back){
    char root=back[back.length()-1];
    cout<<root;
    int k=mid.find(root);
    //左子树
    travel(mid.substr(0,k),back.substr(0,k));
    //右子树
    travel(mid.substr(k+1),back.substr(k,mid.size()-1-k));
}

int main(){
    string mid,back;
    cin>>mid>>back;
    travel(mid,back);
    return 0;
}

怎么会是呢,找子树的时候前提是还有子树可以找,即mid.length()>0

AC代码

#include <bits/stdc++.h>
using namespace std;

void travel(string mid,string back){
    if(mid.length()>0){
        char root=back[back.length()-1];
        cout<<root;
        int k=mid.find(root);
        travel(mid.substr(0,k),back.substr(0,k));
        travel(mid.substr(k+1),back.substr(k,mid.size()-1-k));
    }
}

int main(){
    string mid,back;
    cin>>mid>>back;
    travel(mid,back);
    return 0;
}

根+子树关系才能确定一颗树,这题是中序+后序求前序,还有前序+中序求后序

对于这两种递归写法来说其实都是,利用两序递归建树。

递归建树的时候也就是相当于遍历了一遍,可以直接输出另一个序列。

[USACO3.4] 美国血统 American Heritage - 洛谷

那么同样的这道题画个图也出来了。

 AC代码

#include <bits/stdc++.h>
using namespace std;

void travel(string mid,string pre){
    if(mid.length()>0){
        char root=pre[0];
        int k=mid.find(root);
        travel(mid.substr(0,k),pre.substr(1,k));
        travel(mid.substr(k+1),pre.substr(k+1,mid.length()-1-k));
        cout<<root;
    }
}

int main(){
    string mid,pre;
    cin>>mid>>pre;
    travel(mid,pre);
    return 0;
}

虽说图画的是s-1,但是实际中m-1才代表子树的实际长度,所以里面要写mid.length()-1来取最后一个点。

那么通过前序序列和后序序列能求出有多少个不同的中序序列呢...

遍历问题 - 洛谷

看题解的,如果一个节点只有一个子节点,那么不管这个子节点是在右边还是左边,是不会影响前序和后序的,但是中序会被改变。

手动模拟一下前序和后序,不难发现如果前序的后继节点是后序的前驱节点,那么这是一个孤儿节点

AC代码

#include <bits/stdc++.h>
using namespace std;

int ans=1;
string pre,back;

int main(){
    cin>>pre>>back;
    for(int i=0;i<pre.length();i++){
        for(int j=1;j<back.length();j++){
            if(pre[i]==back[j]&&pre[i+1]==back[j-1])ans<<=1;
        }
    }
    cout<<ans;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值