1119. Pre- and Post-order Traversals (30)
友情提示:這題非常值得自己思考獨(dú)立做出來(lái),請(qǐng)反復(fù)確認(rèn)后再往下拉
1119. Pre- and Post-order Traversals (30)
時(shí)間限制 400 ms內(nèi)存限制 65536 kB
代碼長(zhǎng)度限制 16000 B
判題程序 Special 作者 CHEN, Yue
Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree can be determined by a given pair of postorder and inorder traversal sequences, or preorder and inorder traversal sequences. However, if only the postorder and preorder traversal sequences are given, the corresponding tree may no longer be unique.
Now given a pair of postorder and preorder traversal sequences, you are supposed to output the corresponding inorder traversal sequence of the tree. If the tree is not unique, simply output any one of them.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (<=30), the total number of nodes in the binary tree. The second line gives the preorder sequence and the third line gives the postorder sequence. All the numbers in a line are separated by a space.
Output Specification:
For each test case, first printf in a line "Yes" if the tree is unique, or "No" if not. Then print in the next line the inorder traversal sequence of the corresponding binary tree. If the solution is not unique, any answer would do. It is guaranteed that at least one solution exists. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.
Sample Input 1: 7 1 2 3 4 6 7 5 2 6 7 4 5 3 1 Sample Output 1: Yes 2 1 6 4 7 3 5 Sample Input 2: 4 1 2 3 4 2 4 3 1 Sample Output 2: No 2 1 3 4 題意:給出樹的前序后序遍歷,輸出中序。不能確定時(shí),任選一種輸出分析:和前中、后中一樣,我們需要找到前后遍歷的特殊點(diǎn)
? ? ? ? ? ?我最先感覺,pre的最后一個(gè)(5)和post的第一個(gè)(2),分別代表mid中最右和最左
? ? ? ? ? ?然后發(fā)現(xiàn) 如果pre的第一個(gè)(1) 和post的最后一個(gè)(1)相等,那么1是根節(jié)點(diǎn)
? ? ? ? ? ?_(:з」∠)_接著就迫不及待開始做了,一頓騷操作以后我發(fā)現(xiàn)還做不了
? ? ? ? ? 再看的時(shí)候發(fā)現(xiàn):雖然單看pre沒辦法 確定(2)是(1)的左子樹還是右子樹,但是(1)在post中的前一個(gè)是(3),那么(3)要么是(1)的左子樹要么是(1)的右子樹,而pre當(dāng)中(2)再過去才是(3),所以說(shuō)明,(2)是(1)的左子樹,(3)是(1)的右子樹。那么剩下的(4)(5)(6)(7)呢? 再確認(rèn),(2)和(3)分開以后,(4)(5)(6)(7)明顯就只能是(3)的子樹
? ? ? ? ? 有了這一點(diǎn),就可以開始做了
? ? ? ? ? 用遞歸分治,對(duì)(3)的左右子樹再分別判斷,逐步縮小,直至確認(rèn)。以下圖做詳細(xì)說(shuō)明
?1.首先我們發(fā)現(xiàn)post(1)? 前一位是 3,對(duì)應(yīng)到pre(3)當(dāng)中pre(3)與pre(1)中有間隔。說(shuō)明:(2)是(1)的左子樹,(3)是(1)的右子樹
? ? ? ? ?2.開始遞歸,在橙色圈中我們可以發(fā)現(xiàn),(5)是(3)的右子樹,(4)是3的左子樹
? ? ? ? ?3.post(4)前一位(7)對(duì)應(yīng)到pre當(dāng)中與pre(4)中間仍然數(shù)字間隔,所以(6)是(4)的左子樹,(7)是(4)的右子樹
? ? ? ? ?4.(1)的左子樹(2),可以看出左邊是(1)不能用,右邊則都在(3)的范圍內(nèi),所以(2)兩個(gè)子樹為空
? ? ? ? ?5.(3)的右子樹(5),同上,兩個(gè)子樹為空
? ? ? ? ??
? ? ? ? ?那么,我們要怎么判斷有沒有唯一解呢?如果每一個(gè)非葉節(jié)點(diǎn)都像上面(1)(3)(4)一樣,顯然是有唯一解的,但是如果題中第二個(gè)例子的(3),它的子樹(4)是與(3)緊連的,中間沒有數(shù)字隔開,這是就無(wú)法判斷是左子樹還是右子樹。所以只要當(dāng)我們發(fā)現(xiàn)有某個(gè)非葉節(jié)點(diǎn)只有一個(gè)孩子的時(shí)候,就可以輸出No了
代碼:
#include<iostream> using namespace std; int pre[40]={0}; int post[40]={0}; int n,judge=1; struct node {int data;struct node *lchild,*rchild; }; int find(int a[],int data){for(int i=0; i<n; i++)if(a[i] == data) return i; } struct node *creat(struct node *root, int preStart, int preEnd, int postStart, int postEnd){if(pre[preStart] == post[postEnd]){root = new struct node();root->data = pre[preStart];} if(preStart == preEnd || postStart == postEnd) return root; int i = find(pre, post[postEnd - 1]);//i是root右孩子在pre的索引 int j = find(post, pre[preStart + 1]);//j是root左孩子在post的索引 if(i - preStart >= 2) { root->lchild = creat(root->lchild, preStart+1, i-1, postStart, j);root->rchild = creat(root->rchild, i, preEnd, j+1, postEnd-1);}else{//其實(shí)只剩一種可能,即 i == preStart+1 judge=0;root->rchild = creat(root->rchild, i, preEnd, j+1,postEnd-1);}return root; } void midOut(struct node* root){static int cnt=0;if(root->lchild) midOut(root->lchild);if(root) cnt == 0 ? cout<< root->data : cout<<" "<<root->data;cnt++;if(root->rchild) midOut(root->rchild); } int main() {cin>>n; for(int i=0; i<n; i++)cin>>pre[i];for(int i=0; i<n; i++)cin>>post[i];struct node *root;root = creat(root, 0, n-1, 0, n-1);judge==1? cout<<"Yes"<<endl:cout<<"No"<<endl;midOut(root);cout<<endl; }結(jié)尾:這題感覺有些可惜,因?yàn)榍懊嫦肓撕芫?#xff0c;中間試過很多“奇思妙想”的方法,當(dāng)我想到先確認(rèn)根再確認(rèn)左右子樹時(shí),預(yù)估代碼要寫八九十行而且很繁瑣,就忍不住看了別人的題解。 結(jié)果發(fā)現(xiàn)就是這個(gè)思路 _(:з」∠)_。? 不過那時(shí)候沒想到遞歸,還在撲哧撲哧上下左右想著點(diǎn),所以弄的很復(fù)雜。? 不過人家直接數(shù)組就記錄了mid,然后直接輸出,感覺還是很炫酷。
? ? ? ? ??
轉(zhuǎn)載于:https://www.cnblogs.com/childwang/p/8280262.html
總結(jié)
以上是生活随笔為你收集整理的1119. Pre- and Post-order Traversals (30)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Blog建设好了,好好看φ(゜▽゜*)♪
- 下一篇: Matlab 常用语法速记 1