Sicily 1210. 二叉树

1210. 二叉树

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

在众多的数据结构中,二叉树是一种特殊而重要的结构,有着广泛的应用。二叉树或者是一个结点,或者有且仅有一个结点为二叉树的根,其余结点被分成两个互不相交的子集,一个作为左子集,另一个作为右子集,每个子集又是一个二叉树。

遍历一棵二叉树就是按某条搜索路径巡访其中每个结点,使得每个结点均被访问一次,而且仅被访问一次。最常使用的有三种遍历的方式:

1.前序遍历:若二叉树为空,则空操作;否则先访问根结点,接着前序遍历左子树,最后再前序遍历右子树。

2.中序遍历:若二叉树为空,则空操作;否则先中序遍历左子树,接着访问根结点,最后再前中遍历右子树。

3.后序遍历:若二叉树为空,则空操作;否则先后序遍历左子树,接着后序遍历右子树,最后再访问根结点。

例如图(1)所示的二叉树:

前序遍历的顺序是ABCD,中序遍历的顺序是CBAD,后序遍历的顺序是CBDA。

对一棵二叉树,如果给出前序遍历和中许遍历的结点访问顺序,那么后序遍历的顺序是唯一确定的,也很方便地求出来。但如果现在只知道前序遍历和后序遍历的顺序,中序遍历的顺序是不确定的,例如:前序遍历的顺序是ABCD,而后序遍历的顺序是CBDA,那么就有两课二叉树满足这样的顺序(见图(1)和图(2))。

现在的问题是给定前序遍历和后序遍历的顺序,要求出总共有多少棵不同形态的二叉树满足这样的遍历顺序。

Input

整个输入有两行,第一行给出前序遍历的访问顺序,第二行给出后序遍历的访问顺序。
二叉树的结点用一个大写字母表示,不会有两个结点标上相同字母。输入数据不包含空格,且保证至少有一棵二叉树符合要求。

Output

输出一个整数,为符合要求的不同形态二叉树的数目。

Sample Input

ABCD
CBDA

Sample Output

2

Problem Source

ZSUACM Team Member


题目解析:很明显,就是已知树的前序遍历和后序遍历,求该树有几种形态。

              先复习一下树的三种遍历:

              前序遍历:根->左子树->右子树;中序遍历:左子树根->根->右子树;后序遍历:左子树->右子树->根。

             由前后两种遍历不能确定一颗树,是因为前后序遍历中,左子树和右子树(或者说左节点和右节点)在遍历顺序上是相邻的,不像中序遍历那样有根节点可以加以区分。而问题就出现在,若果当前节点是单子树的,在前后序遍历上就无法区分它究竟是左子树还是右子树。若这种情况出现了n次,那么结果就有2的n次方个可能。所以,解决这个问题的关键就转移到了寻找单子树节点的个数上。

               通过简单的构图,可以发现对于单子树的存在,根节点和子树节点在前后序遍历上是相邻的,而出现的顺序是相反的。通过这个规律就可以找到这种特殊存在的个数。

             这题坑就坑在,不用输出换行啊%>_<%,两次PE,囧死了。注意看输出要求就行。。。

代码如下:

#include<iostream>
#include<string>
#include<cmath>
using namespace std;

string pre,post;
int ans;

int solve(string x,string y)
{
    int len1=x.size();
    int len2=y.size();
    int cnt=0;
    for(int i=0;i<len1;i++)
    {
        for(int j=len2-1;j>=0;j--)
        {
            if(x[i]==y[j]&&x[i+1]==y[j-1])
            {
                cnt++;
                break;
                }
        }
    }
    return cnt;
}

int main()
{
        cin>>pre>>post;
        ans=solve(pre,post);
        cout <<(int)pow(2.0,ans);
        
         return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值