pat甲级 1119 Pre- and Post-order Traversals (30 分) (二叉树的后序和先序遍历求中序遍历)

题目链接:传送门

思路:这个题是通过二叉树的先序遍历和后序遍历推中序,但是先序和后序是无法唯一确定一颗二叉树的,为什么呢?首先设两个序列为pre[n] , 和 post[n] , 先序的第一个节点pre[0]和后序最后一个节post[ n - 1 ]点是头结点,如果头结点有两棵子树,那么结构是确定的,比如后序的倒数第二个节点p[n - 2]是头结点的右子树,在先序中找到这个节点的位置pre[ l ] , 那pre[2]到pre[l - 1]是头结点的左子树。但是如果 l = 2 ,即头结点只有一颗子树 那么我们不确定pre[2] — pre[n - 1]是头结点的左子树还是头结点的右子树,但是应为只有一颗子树,不论把它当左子树还是右子树,都不会影响子树的结构,所以遇到这种情况可以全当成右子树的来处理.

对于本题,只需判断是否有一个子树的情况即可,如果有的话就有两种以上二叉树,输出"No",否则输出"Yes"。
然后直接存储当前遍历到的头结点即可。(具体请看代码)

代码:

#include <bits/stdc++.h>

using namespace std;

const int maxn = 100;

int pre[maxn] , post[maxn];
int n;
vector <int> ans;
bool flag;

void dfs(int pl , int pr , int pol , int por) {
	if(pl == pr)  {
		ans.push_back(pre[pl]);
		return;	
	}
	int i = 0;
	while(i + pl + 1 <= pr && pre[i + pl + 1] != post[por - 1])i++;
	if(i > 0) {
		dfs( pl + 1 , pl + i , pol , pol + i - 1);
	}
	else flag = 1;
	ans.push_back(pre[pl]);
	dfs(pl + i + 1 , pr , pol + i , por - 1);
}


int main() {
	ios::sync_with_stdio(0);
	cin >> n;
	for(int i = 0 ; i < n ; i++) {
		cin >> pre[i];
	}
	for(int i = 0 ; i < n ; i++) {
		cin >> post[i];
	}
	flag = 0;
	dfs(0 , n - 1, 0 , n - 1);
	if(!flag) cout << "Yes\n";
	else cout << "No\n";
	for(int i = 0 ; i < ans.size() ; i++) {
		if(i > 0)cout << " ";
		cout << ans[i];
	}
	cout << "\n";
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章