# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def constructFromPrePost(self, preorder, postorder):
if not preorder:
return None
root = TreeNode(preorder[0])
if len(preorder) == 1:
return root
# Find the left subtree root in postorder
left_root_val = preorder[1]
left_subtree_size = postorder.index(left_root_val) + 1
root.left = self.constructFromPrePost(preorder[1:left_subtree_size+1], postorder[:left_subtree_size])
root.right = self.constructFromPrePost(preorder[left_subtree_size+1:], postorder[left_subtree_size:-1])
return root
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* constructFromPrePost(vector& preorder, vector& postorder) {
if (preorder.empty()) return nullptr;
TreeNode* root = new TreeNode(preorder[0]);
if (preorder.size() == 1) return root;
int left_root_val = preorder[1];
int left_subtree_size = 0;
for (int i = 0; i < postorder.size(); ++i) {
if (postorder[i] == left_root_val) {
left_subtree_size = i + 1;
break;
}
}
root->left = constructFromPrePost(
vector(preorder.begin() + 1, preorder.begin() + 1 + left_subtree_size),
vector(postorder.begin(), postorder.begin() + left_subtree_size)
);
root->right = constructFromPrePost(
vector(preorder.begin() + 1 + left_subtree_size, preorder.end()),
vector(postorder.begin() + left_subtree_size, postorder.end() - 1)
);
return root;
}
};
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {
return build(preorder, 0, preorder.length - 1, postorder, 0, postorder.length - 1);
}
private TreeNode build(int[] preorder, int preStart, int preEnd, int[] postorder, int postStart, int postEnd) {
if (preStart > preEnd) return null;
TreeNode root = new TreeNode(preorder[preStart]);
if (preStart == preEnd) return root;
int leftRootVal = preorder[preStart + 1];
int leftIndex = postStart;
while (postorder[leftIndex] != leftRootVal) leftIndex++;
int leftSize = leftIndex - postStart + 1;
root.left = build(preorder, preStart + 1, preStart + leftSize, postorder, postStart, leftIndex);
root.right = build(preorder, preStart + leftSize + 1, preEnd, postorder, leftIndex + 1, postEnd - 1);
return root;
}
}
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {number[]} preorder
* @param {number[]} postorder
* @return {TreeNode}
*/
var constructFromPrePost = function(preorder, postorder) {
if (preorder.length === 0) return null;
const root = new TreeNode(preorder[0]);
if (preorder.length === 1) return root;
const leftRootVal = preorder[1];
const leftSubtreeSize = postorder.indexOf(leftRootVal) + 1;
root.left = constructFromPrePost(preorder.slice(1, leftSubtreeSize + 1), postorder.slice(0, leftSubtreeSize));
root.right = constructFromPrePost(preorder.slice(leftSubtreeSize + 1), postorder.slice(leftSubtreeSize, postorder.length - 1));
return root;
};
preorder and postorder that represent the preorder and postorder traversal of a binary tree, construct and return the binary tree that generated these traversals.
preorder and postorder is unique.preorder and inorder (or postorder and inorder), since the inorder traversal gives a clear left/right subtree boundary. However, with only preorder and postorder, it's less obvious.
The key insight is that:
preorder traversal visits nodes in root - left - right order.postorder traversal visits nodes in left - right - root order.preorder array is empty, return null (no nodes to construct).
preorder is always the root of the current subtree.
preorder is the root of the left subtree. Find this value in postorder to determine the size of the left subtree (since postorder lists all left subtree nodes before the right subtree and root).
preorder and postorder.preorder = [1, 2, 4, 5, 3, 6, 7]postorder = [4, 5, 2, 6, 7, 3, 1]preorder is 1 (the root).postorder (index 2). So, the left subtree has 3 nodes (4, 5, 2).preorder[1:4] = [2, 4, 5], postorder[0:3] = [4, 5, 2]preorder[4:] = [3, 6, 7], postorder[3:6] = [6, 7, 3][4], [4] (returns node 4)
[5], [5] (returns node 5)
[6], [6] (returns node 6)
[7], [7] (returns node 7)
postorder (which is O(n) per node in the naive implementation). With further optimization (using a hash map to store value-to-index mappings), we can reduce this to O(1) per lookup.