二叉树的计数
时间限制: 1 Sec 内存限制: 64 MB[提交][状态][我的提交]
题目描述
输入
第1行:二叉树的前序遍历顺序 第2行:后序遍历顺序
输出
第1行:1个整数,表示所有可能的二叉树的数量
样例输入
(如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)
ABC
CBA
样例输出
4
只给出先序遍历和中序遍历之所以无法确定一棵二叉树, 是因为不能确定某一非叶子节点具有的子树是其左子树还是右子树.
如:pre = “ABCD” 和 pos = "CBDA"
由pre[0] == pos[3],B可能是A的左子树,又,在pos中,B后面还有D,没有紧跟A,所以可知A有两子树,B为A左子树,C为B的子树,可以是左子树也可以是右子树,于是此处产生两种可能的形态,返回pre中可得D为A右子树。
答案为2。
所以可以得出结论,若以一棵最小子树(共3个结点)为单位, 当遍历到父亲结点时,若在pre和pos中其只有一个点作为叶子节点,其必将有两种形态。
假设所给出的pre和pos都是所有结点度为2或0的树,没有度为1的结点,那么当到分离到最小单位时,若子串长度为1,则证明其有此结点,长度小于等于0即无此结点。
substr(a, b);//a为起始位置(下标从0开始), b为子串长度
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
string A, B;
int work(string pre, string pos){
if(pre.size() <= 0) return 0;
if(pre.size() == 1) return 1;
int p = pre.find(pos[1]);
int fro, aft;
fro = work(pre.substr(1, p + 1), pos.substr(0, p + 1));
aft = work(pre.substr(p + 2, pre.size() - p - 1), pos.substr(p + 1, pos.size() - p - 1));
if(!fro) return aft * 2;
else if(!aft) return fro * 2;
else return fro * aft;
}
int main(){
cin>>A>>B;
printf("%d\n", work(A, B));
}