Time Limit: 1 secs, Memory Limit: 32 MB
在众多的数据结构中,二叉树是一种特殊而重要的结构,有着广泛的应用。二叉树或者是一个结点,或者有且仅有一个结点为二叉树的根,其余结点被分成两个互不相交的子集,一个作为左子集,另一个作为右子集,每个子集又是一个二叉树。
遍历一棵二叉树就是按某条搜索路径巡访其中每个结点,使得每个结点均被访问一次,而且仅被访问一次。最常使用的有三种遍历的方式:
1.前序遍历:若二叉树为空,则空操作;否则先访问根结点,接着前序遍历左子树,最后再前序遍历右子树。
2.中序遍历:若二叉树为空,则空操作;否则先中序遍历左子树,接着访问根结点,最后再前中遍历右子树。
3.后序遍历:若二叉树为空,则空操作;否则先后序遍历左子树,接着后序遍历右子树,最后再访问根结点。
例如图(1)所示的二叉树:
前序遍历的顺序是ABCD,中序遍历的顺序是CBAD,后序遍历的顺序是CBDA。
对一棵二叉树,如果给出前序遍历和中许遍历的结点访问顺序,那么后序遍历的顺序是唯一确定的,也很方便地求出来。但如果现在只知道前序遍历和后序遍历的顺序,中序遍历的顺序是不确定的,例如:前序遍历的顺序是ABCD,而后序遍历的顺序是CBDA,那么就有两课二叉树满足这样的顺序(见图(1)和图(2))。
现在的问题是给定前序遍历和后序遍历的顺序,要求出总共有多少棵不同形态的二叉树满足这样的遍历顺序。
整个输入有两行,第一行给出前序遍历的访问顺序,第二行给出后序遍历的访问顺序。
二叉树的结点用一个大写字母表示,不会有两个结点标上相同字母。输入数据不包含空格,且保证至少有一棵二叉树符合要求。
输出一个整数,为符合要求的不同形态二叉树的数目。
ABCD CBDA
2
题目分析
二叉树,知道前序后序求可能的方法数
由前序中序获取唯一的后序
由后序中序获取唯一的前序
但是由前序后序无法获得唯一的中序
因为当某棵树只有一个孩子节点时,无法判定这是左孩子右孩子,此时可能的中序将成倍递增
具体做法是
由题目可知
当pre[1] == post[post.length()-2]时,只有一个子树
否则分别获得左右子树
进行递归,当传进来的字符串长度为1时结束递归
#include <iostream> int count; void deal(std::string pre, std::string post) { if (pre.length() == 1) return; if (pre[1] == post[post.length()-2]) { count *= 2; std::string lpre = ""; for (int i = 1; i < pre.length(); ++i) lpre += pre[i]; std::string lpost = ""; for (int i = 0; i < post.length()-1; ++i) lpost += post[i]; //std::cout << lpre << "-------------------------" << lpost << std::endl; deal(lpre, lpost); return; } int indexl = 1, indexr = 0; std::string lpre = "", lpost = "", rpre = "", rpost = ""; while (true) { lpre += pre[indexl++]; lpost += post[indexr++]; if (pre[1] == post[indexr-1]) break; } while (indexl != pre.length()) { rpre += pre[indexl++]; rpost += post[indexr++]; } //std::cout << lpre << "===" << rpre << std::endl; //std::cout << lpost << "===" << rpost << std::endl; deal(lpre, lpost); deal(rpre, rpost); } int main() { std::string pre, post; std::cin >> pre >> post; count = 1; deal(pre, post); std::cout << count; }