例1:給定一棵二叉樹的後序遍歷和中序遍歷,請你輸出其層序遍歷的序列。html
題目連接:https://www.patest.cn/contests/gplt/L2-006c++
#include<bits/stdc++.h> using namespace std; const int MAXN = 100 + 10; int post[MAXN], in[MAXN]; int lchild[MAXN], rchild[MAXN]; vector<int> ans; int dfs(int pL, int pR, int iL, int iR, int root){ if(pL > pR) return 0; int id = iL; while(in[id] != root) ++id; int cnt = id - iL; lchild[root] = dfs(pL, pL + cnt - 1, iL, id - 1, post[pL + cnt - 1]); rchild[root] = dfs(pL + cnt, pR - 1, id + 1, iR, post[pR - 1]); return root; } void bfs(int root){ queue<int> q; q.push(root); while(!q.empty()){ int x = q.front(); ans.push_back(x); q.pop(); if(lchild[x]) q.push(lchild[x]); if(rchild[x]) q.push(rchild[x]); } } int main(){ int N; scanf("%d", &N); for(int i = 0; i < N; ++i){ scanf("%d", &post[i]); } for(int i = 0; i < N; ++i){ scanf("%d", &in[i]); } int root = post[N - 1]; dfs(0, N - 1, 0, N - 1, root); bfs(root); int len = ans.size(); for(int i = 0; i < len; ++i){ printf("%d", ans[i]); if(i == len - 1) printf("\n"); else printf(" "); } return 0; }
例2:已知前序遍歷和中序遍歷,求後序遍歷。數組
題目連接:https://www.patest.cn/contests/pat-a-practise/1138post
#include<bits/stdc++.h> using namespace std; const int MAXN = 50000 + 10; int pre[MAXN], in[MAXN]; vector<int> ans; void dfs(int pL, int pR, int iL, int iR, int root){ if(pL > pR) return; int id = iL; while(in[id] != root) ++id; int cnt = id - iL; dfs(pL + 1, pL + cnt, iL , id - 1, pre[pL + 1]); dfs(pL + cnt + 1, pR, id + 1, iR, pre[pL + cnt + 1]); ans.push_back(root); } int main(){ int N; scanf("%d", &N); for(int i = 0; i < N; ++i){ scanf("%d", &pre[i]); } for(int i = 0; i < N; ++i){ scanf("%d", &in[i]); } int root = pre[0]; dfs(0, N - 1, 0, N - 1, root); printf("%d\n", ans[0]); return 0; }
另外一種作法:spa
由於輸出的是後序遍歷(左右中)第一個元素,所以對於某元素,code
若是有左子樹的話,就不用研究右子樹了;htm
若是沒有左子樹,就研究右子樹;blog
若是左右子樹都沒有,就研究他自己。(遇到的第一個葉子結點就是答案)get
#include<bits/stdc++.h> using namespace std; const int MAXN = 50000 + 10; int pre[MAXN], in[MAXN]; map<int, int> mp; void dfs(int pL, int pR, int iL, int iR, int root){ if(pL > pR) return; int id = mp[root]; int cnt = id - iL; if(iL != id){ dfs(pL + 1, pL + cnt, iL, id - 1, pre[pL + 1]); } else if(iR != id){ dfs(pL + cnt + 1, pR, id + 1, iR, pre[pL + cnt + 1]); } else{ printf("%d\n", root); return; } } int main(){ int N; scanf("%d", &N); for(int i = 0; i < N; ++i){ scanf("%d", &pre[i]); } for(int i = 0; i < N; ++i){ scanf("%d", &in[i]); mp[in[i]] = i; } int root = pre[0]; dfs(0, N - 1, 0, N - 1, root); return 0; }
例3:已知前序遍歷和後序遍歷,求中序遍歷。it
思路:前序遍歷的第一個元素是根。
若只有左子樹,則前序遍歷的第二個元素和後序遍歷的倒數第二個元素相同,且都是左子樹的根;
若只有右子樹,則前序遍歷的第二個元素和後序遍歷的倒數第二個元素相同,且都是右子樹的根;
若既有左子樹又有右子樹,則前序遍歷的第二個元素是左子樹的根,後序遍歷的倒數第二個元素是右子樹的根;
即,若前序遍歷的第二個元素和後序遍歷的倒數第二個元素相同,則對於當前根結點來講有兩種可能,要麼只有左子樹,要麼只有右子樹。這兩種狀況下,前序遍歷是相同的,後序遍歷也是相同的,但中序遍歷不一樣。
(1)求任意一種中序遍歷。
題目連接:https://www.patest.cn/contests/pat-a-practise/1119
#include<cstdio> #include<vector> #include<map> using namespace std; const int MAXN = 30 + 10; int pre[MAXN], pos[MAXN]; int cnt; map<int, int> mp1; map<int, int> mp2; vector<int> ans; void dfs(int prL, int prR, int poL, int poR, int root){ if(prL > prR) return; if(prL == prR){ ans.push_back(root); return; } int tmp1 = pre[prL + 1]; int tmp2 = pos[poR - 1]; if(tmp1 != tmp2){ dfs(mp1[tmp1], mp1[tmp2] - 1, poL, mp2[tmp1], pre[mp1[tmp1]]); ans.push_back(root); dfs(mp1[tmp2], prR, mp2[tmp1] + 1, poR - 1, pre[mp1[tmp2]]); } else{ ++cnt; dfs(mp1[tmp1], prR, poL, mp2[tmp1], pre[mp1[tmp1]]); ans.push_back(root); } } int main(){ int N; scanf("%d", &N); for(int i = 0; i < N; ++i){ scanf("%d", &pre[i]); mp1[pre[i]] = i; } for(int i = 0; i < N; ++i){ scanf("%d", &pos[i]); mp2[pos[i]] = i; } int root = pre[0]; dfs(0, N - 1, 0, N - 1, root); if(cnt >= 1) printf("No\n"); else printf("Yes\n"); int len = ans.size(); for(int i = 0; i < len; ++i){ printf("%d", ans[i]); if(i == len - 1) printf("\n"); else printf(" "); } return 0; }
(2)求中序遍歷可能的種數。
題目連接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1832
思路:運算結果涉及高精度計算。
#include<cstdio> #include<vector> #include<map> using namespace std; const int MAXN = 10000 + 10; const int MOD = 1000000000; int pre[MAXN], pos[MAXN]; int cnt; map<int, int> mp1; map<int, int> mp2; int ans[MAXN]; void dfs(int prL, int prR, int poL, int poR){ if(prL >= prR) return; int tmp1 = pre[prL + 1]; int tmp2 = pos[poR - 1]; if(tmp1 != tmp2){ dfs(mp1[tmp1], mp1[tmp2] - 1, poL, mp2[tmp1]); dfs(mp1[tmp2], prR, mp2[tmp1] + 1, poR - 1); } else{ ++cnt; dfs(prL + 1, prR, poL, poR - 1); } } void solve(int n, int k){//將最終的結果每隔9位數存在ans數組中 int len = 1; ans[1] = 1; while(k--){ for(int i = 1; i <= len; ++i){ ans[i] *= n; } for(int i = 1; i <= len; ++i){ ans[i + 1] += ans[i] / MOD; ans[i] %= MOD; } if(ans[len + 1]) ++len; } for(int i = len; i >= 1; --i){ if(i == len) printf("%d", ans[i]); else printf("%09d", ans[i]); } printf("\n"); } int main(){ int N; scanf("%d", &N); for(int i = 0; i < N; ++i){ scanf("%d", &pre[i]); mp1[pre[i]] = i; } for(int i = 0; i < N; ++i){ scanf("%d", &pos[i]); mp2[pos[i]] = i; } dfs(0, N - 1, 0, N - 1); solve(2, cnt);//計算2的cnt次方,不取模 return 0; }