輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。java
根據二叉樹的前序和中序遍歷,重建二叉樹。數組
咱們知道:spa
前序遍歷:根節點,左子樹,右子樹。code
中序遍歷:左子樹,根節點,右子樹。blog
後序遍歷:左子樹,右子樹,根節點。遞歸
能夠發現,前序遍歷的第一個數即是整個數的根節點,而這個數在中序遍歷中,又將數組分紅兩部分,其中左邊即是左子樹,右邊是右子樹,根據劃分出來的左右子樹,咱們又能夠返回前序遍歷,去查看左右子樹數組中的第一個元素,這樣就能夠遞歸求解這個問題了。索引
咱們要記錄好每次遞歸執行時的序列索引,這樣有利於咱們求解子問題須要數組的索引,前序遍歷數組的左右索引記爲leftPre,rightPre,中序遍歷數組的左右索引是leftIn和rightIn。get
則左子樹的前序遍歷數組左索引是leftPre+1,由於leftPre指的元素是root。io
左子樹的前序遍歷數組右索引是leftPre+flag-leftIn,其中flag是root在中序遍歷數組中的索引,而flag-leftIn正好是左子樹元素的個數。class
左子樹的中序遍歷數組索引是leftPre和flag-1,由於flag是咱們找到的root元素,左邊天然就是新的中序遍歷數組了。
右子樹的前序遍歷數組左索引是leftPre+flag-leftIn+1,其實也就是左子樹的右索引加1,由於在前序遍歷中,左右子樹是相連的。rightPre天然就成了右索引。
右子樹的中序遍歷數組索引是flag+1和rightIn。
不過在求解中,每次都要在中序遍歷的數組中去查找根節點的索引,咱們能夠開始的時候將索引存進map中,須要的時候直接取,這樣能夠下降時間複雜度。
C++
class Solution { public: TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) { return helper(pre, vin, 0, pre.size()-1, 0, vin.size()-1); } TreeNode* helper(vector<int>& preorder, vector<int>& inorder, int leftPre, int rightPre, int leftIn, int rightIn){ if(leftPre > rightPre) return nullptr; TreeNode* root = new TreeNode(preorder[leftPre]); if(leftPre == rightPre) return root; else{ int i = leftIn; for(;i <= rightIn; ++i){ if(inorder[i] == preorder[leftPre]) break; } root->left = helper(preorder, inorder, leftPre+1, leftPre+i-leftIn, leftIn, i-1); root->right = helper(preorder, inorder, leftPre+i+1-leftIn, rightPre, i+1, rightIn); return root; } } };
Java
//use HashMap import java.util.HashMap; public class Solution { public TreeNode reConstructBinaryTree(int [] pre,int [] in) { map = new HashMap<>(); for(int i = 0; i < in.length; ++i){ map.put(in[i], i); } return helper(pre, in, 0, pre.length-1, 0, in.length-1); } public TreeNode helper(int[] preorder, int[] inorder, int leftPre, int rightPre, int leftIn, int rightIn){ if(leftPre > rightPre) return null; TreeNode root = new TreeNode(preorder[leftPre]); if(leftPre == rightPre) return root; else{ int i = map.get(preorder[leftPre]); root.left = helper(preorder, inorder, leftPre+1, leftPre+i-leftIn, leftIn, i-1); root.right = helper(preorder, inorder, leftPre+i-leftIn+1, rightPre, i+1, rightIn); return root; } } private HashMap<Integer, Integer> map; }