題目鏈接:傳送門
思路:這個題是通過二叉樹的先序遍歷和後序遍歷推中序,但是先序和後序是無法唯一確定一顆二叉樹的,爲什麼呢?首先設兩個序列爲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;
}