《劍指offer》學習筆記_面試題7_重建二叉樹
阿新 • • 發佈:2018-12-17
-
一、前序遍歷與中序遍歷重建二叉樹
-
1.題目描述
輸入一顆二叉樹的前序遍歷序列和中序遍歷序列,請根據這兩個序列重建一棵二叉樹。(假設輸入的前序遍歷和中序遍歷的結果都不包含重複的數字)
-
2.思路
前序遍歷的第一個數就是二叉樹的根結點,這個根結點通常是在中序遍歷的中間位置。在中序遍歷中,根結點左邊的數都在二叉樹的左子樹中,右邊的數都在二叉樹的右子樹中。因此通過中序遍歷,可以確定左子樹結點的個數和右子樹結點的個數。在前序遍歷中,根結點後面先是左子樹的所有結點,之後是右子樹的所有結點。
前序遍歷和中序遍歷的關係:
-
3.C++實現
class Solution { public: TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { if(preorder.size()==0)return nullptr; if(preorder.size()!=inorder.size())return nullptr; return create(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1); } /* ps:前向遍歷的開始位置; pe:前向遍歷的結束位置; is:中序遍歷的開始位置; ie:中序遍歷的結束位置; */ TreeNode* create(vector<int>& preorder,vector<int>& inorder,int ps,int pe,int is,int ie){ if(ps>pe)return nullptr; TreeNode* node = new TreeNode(preorder[ps]); int pos;//儲存前序遍歷的第一個數字在中序遍歷中的位置 for(int i = is;i<=ie;i++){ if(inorder[i]==node->val){ pos = i; break; } } int leftLen = pos - is;//左子樹中的結點數 node->left = create(preorder,inorder,ps+1,ps+leftLen,is,pos-1); node->right = create(preorder,inorder,ps+leftLen+1,pe,pos+1,ie); return node; } };
-
二、後序遍歷與中序遍歷重建二叉樹
-
1.題目描述
輸入一顆二叉樹的後序遍歷序列和中序遍歷序列,請根據這兩個序列重建一棵二叉樹。(假設輸入的後序遍歷和中序遍歷的結果都不包含重複的數字)
-
2.思路
同前面的重建二叉樹的思路相似,只不過後序遍歷的根結點在序列的末尾,然後前面是所有右子樹的結點,再前面是所有左子樹的結點。
-
3.C++實現
class Solution { public: TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { if(inorder.size()==0)return nullptr; if(inorder.size()!=postorder.size())return nullptr; return create(inorder,postorder,0,inorder.size()-1,0,postorder.size()-1); } TreeNode* create(vector<int>& inorder,vector<int>& postorder,int is,int ie,int ps,int pe){ if(ps>pe)return nullptr; TreeNode* node = new TreeNode(postorder[pe]); int pos = 0; for(int i=is;i<=ie;i++){ if(inorder[i]==node->val){ pos = i; break; } } int rightLen = ie - pos; node->right = create(inorder,postorder,pos+1,ie,pe-rightLen,pe-1); node->left = create(inorder,postorder,is,pos-1,ps,pe-rightLen-1); return node; } };