3965 Binary Tree Restoring (dfs)
阿新 • • 發佈:2018-12-18
題目
題意
給出一顆二叉樹的兩種 序列,即同一層上沒有明確的左右子樹概念,兩種序列可以以根節點-左/右子樹-另一顆子樹的順序實現。求一顆滿足兩種 序列的二叉樹,輸出每一個節點的父親節點。題目保證有解
思路
因為是一顆樹的重構,我們可以同時從兩棵樹的 序列入手,我們可以分別在兩個序列上,找到當前子樹所在的區間,並且可以通過判斷當前位在兩個序列中的值是否相同,來判斷當前父親節點需要兩棵子樹還是一棵子樹。 原因是這樣的,因為兩個 序列,是以這樣的形勢展現的: _ _ _ _ 或 _ _ _ _ 那麼當我們確定一個根後,如果他們的後一個節點是相同的,我們可以判斷後一個節點引導了一個連在當前根的子樹。如果當前根的後一個值在兩個序列中是不同的,那麼這兩個值各自引導了一個連在當前根的子樹。兒通過查詢兩個值的兩個序列中的位置,我們可以確定子樹所在的序列,然後遞迴呼叫。 需要注意的一點是,因為我們的樹是二叉的,所以當前根有兩棵子樹時,是不用考慮的,因為子樹長度是確定的,而如果當前根只有一棵子樹的話,我們需要判斷是否存在另一顆子樹。
程式碼
遞迴呼叫實現
const int maxn = 1e5+5;
int a[maxn], b[maxn], pa[maxn] , pb[maxn];
int pre[maxn];
void build(int root, int la, int lb, int &len){
if(len == 0) return;
if(a[la] != b[lb]){
pre[a[la]] = root;
pre[b[lb]] = root; // la-ls, lb-rs;
int ls_la = la+1, ls_ra = pa[b[lb]]-1;
int ls_len = ls_ra - ls_la + 1;
int rs_lb = lb+1, rs_rb = pb[a[la]]-1;
int rs_len = rs_rb - rs_lb + 1;
int ls_lb = pb[a[la]]+1;
int rs_la = pa[b[lb]]+1;
build(a[la], ls_la, ls_lb, ls_len); // ls
build(b[lb], rs_la, rs_lb, rs_len); // rs
len = ls_len + rs_len + 2;
return ;
}
else {
pre[a[la]] = root;
int ls_la = la+1, ls_lb = lb+1, ls_len = len-1;
build(a[la], ls_la, ls_lb, ls_len);
if(ls_len+1 < len){
int rs_root = a[la+ls_len+1], rs_la = la+ls_len+2, rs_lb = lb+ls_len+2;
int rs_len = len - ls_len - 2;
pre[rs_root] = root;
build(rs_root, rs_la, rs_lb, rs_len);
len = ls_len + rs_len + 2;
}
}
}
int main()
{
int T, n;
sd(T);
while(T--){
sd(n);
rep(i, 0, n) {
sd(a[i]);
pa[a[i]] = i;
}
rep(i, 0, n) {
sd(b[i]);
pb[b[i]] = i;
}
build(0, 0, 0, n);
rep(i, 1, n+1){
printf("%d%c", pre[i], i==n?'\n':' ');
}
}
return 0;
}