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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章