1 / \ 2 3 / \ / \ 4 5 6 7 對於上圖的樹來講, index: 0 1 2 3 4 5 6 先序遍歷爲: 1 2 4 5 3 6 7 中序遍歷爲: 4 2 5 1 6 3 7 1. 先序遍歷的第一個節點爲根節點。 2. 中序遍歷中根節點是左子樹右子樹的分割點。
因此這道題能夠用遞歸的方法解決。
經過先序遍歷找到第一個點做爲根節點,在中序遍歷中找到根節點並記錄index。此處用hashmap來存儲, key爲中序遍歷節點值 value爲index
由於中序遍歷中根節點左邊爲左子樹,因此能夠記錄左子樹的長度並在先序遍歷中依據這個長度找到左子樹的區間,用一樣方法能夠找到右子樹的區間。
遞歸的創建好左子樹和右子樹就好。post
時間O(n) 空間用了一個map 爲O(n)ui
public TreeNode buildTree(int[] preorder, int[] inorder) { if (preorder == null || inorder == null || preorder.length == 0 || inorder.length == 0 || preorder.length != inorder.length) { return null; } int len = preorder.length; HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); for (int i = 0; i < len; i++) { map.put(inorder[i], i); } return helper(preorder, 0 , len - 1, inorder, 0, len - 1, map); } public TreeNode helper(int[] preorder, int pstart, int pend, int[] inorder, int istart, int iend, HashMap<Integer, Integer> map) { if (pstart > pend || istart > iend) { return null; } TreeNode root = new TreeNode(preorder[pstart]); int index = map.get(root.val); root.left = helper(preorder, pstart + 1, pstart + index - istart, inorder, istart, index - 1, map); root.right = helper(preorder, pstart + index - istart + 1, pend, inorder, index + 1, iend, map); return root; }
時間O(n) 空間用了一個map 爲O(n)code
public TreeNode buildTree(int[] inorder, int[] postorder) { int len = inorder.length; HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); for (int i = 0; i < len; i++) { map.put(inorder[i], i); } return helper(inorder, 0, len - 1, postorder, 0 , len - 1, map); } public TreeNode helper(int[] inorder, int istart, int iend, int[] postorder, int pstart, int pend, HashMap<Integer, Integer> map) { if (istart > iend || pstart > pend) { return null; } TreeNode root = new TreeNode(postorder[pend]); int index = map.get(root.val); root.left = helper(inorder, istart, index - 1, postorder, pstart, pstart + index - istart - 1, map); root.right = helper(inorder, index + 1, iend, postorder, pstart + index - istart, pend - 1, map); return root; }