Description:
Given preorder and inorder traversal of a tree, construct the binary tree.
Link:
題目意思:
給出二叉樹的先序和中序遍歷結果,重構二叉樹。
解題方法:
對于先序遍歷分析:根左右
根節點永遠在數組第一個(無論是整個二叉樹的先序遍歷還是二叉樹中一個子樹的先序遍歷),在根節點之后,數組中的元素可以分為左右子樹兩組(并且元素位置不會交叉)。
對于中序遍歷分析:左根右
如果在數組中能確定代表根節點的元素,那么該元素左邊的部分為根節點的左子樹,右邊為右子樹。
總結:
由以上觀察可以總結出解題方法。最開始由先序得到一個根節點(此時是一棵樹樹),然后通過在中序上找到該節點可以知道這個根節點的左右子樹總共有多少節點,再從先序中劃分出左右子樹,得到兩個根節點(得到左右子樹兩棵樹)。使用分治的思想可以完成。
Tips:
在中序遍歷數組中找根節點位置時候每次操作為O(N),如果使用哈希表可以減小到O(1)。
Time Complexity:
使用哈希表為O(N),遍歷則為O(N^2)
完整代碼:
class Solution { public: unordered_map<int, int> um; //哈希表記錄中序數組每個元素位置 TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { if(preorder.size() != inorder.size()) return NULL; buildindex(inorder); return build(preorder, 0, preorder.size() - 1, 0, inorder.size() - 1);//用幾個int變量來實現對數組的分割 } void buildindex(vector<int>& inorder)//建立索引 { for(int i = 0; i < inorder.size(); i++) um[inorder[i]] = i; } TreeNode* build(vector<int>& preorder, int prestart, int preend, int instart, int inend) { if(prestart > preend) return NULL; TreeNode *temp =new TreeNode(preorder[prestart]); int poi = um[temp->val]; temp->left = build(preorder, prestart + 1, prestart + poi - instart, instart, poi-1); temp->right = build(preorder, prestart + poi - instart + 1, preend, poi + 1, inend); return temp; } };
此題參考了:http://blog.csdn.net/sgbfblog/article/details/7783935 的帖子。