105. Construct Binary Tree from Preorder and Inorder Traversal
1. Description
Given preorder and inorder traversal of a tree, construct the binary tree.
2. Note
- You may assume that duplicates do not exist in the tree.
3. Solutions
My Accepted Solution
n is the number of nodes in i_root
Time complexity: O(n)
Space complexity: O(n)
class Solution
{
private:
vector<int> preorderTraversal;
vector<int> inorderTraversal;
// right means the last valid item
TreeNode* buildTree(int preLeft, int preRight, int inLeft, int inRight)
{
if(preLeft > preRight || inLeft > inRight) return nullptr;
TreeNode *result = new TreeNode(preorderTraversal[preLeft]);
int inorderRootIndex = find(inorderTraversal.begin(), inorderTraversal.end(), preorderTraversal[preLeft]) - inorderTraversal.begin();
int leftChildNodesCount = inorderRootIndex - inLeft;
int rightChildNodesCount = inRight - inorderRootIndex;
result->left = buildTree(preLeft + 1, preLeft + leftChildNodesCount, inLeft, inorderRootIndex - 1);
result->right = buildTree(preRight - rightChildNodesCount + 1, preRight, inorderRootIndex + 1, inRight);
return result;
}
public:
// TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
TreeNode* buildTree(const vector<int> &i_preorderTraversal, vector<int> &i_inorderTraversal)
{
preorderTraversal = i_preorderTraversal;
inorderTraversal = i_inorderTraversal;
return buildTree(0, preorderTraversal.size() - 1, 0, inorderTraversal.size() - 1);
}
};
3.1 Iteration
n is the number of nodes in i_root
Time complexity: O(n)
Space complexity: O(n)
// the iteration method is pretty hard 🥺, I learn it from the Leetcode(Chinese)
// for any insecutive two nodes A and B in preorder, they only have two possible relationships
// 1. A is the parent of B, while B is the left child of A
// 2. A doesn't have left child, while B is the right child of one parent of A(or it self)
class Solution
{
public:
// TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
TreeNode* buildTree(const vector<int> &i_preorderTraversal, vector<int> &i_inorderTraversal)
{
// Leetcode usually don't give vicious inputs and they will give constranints or notes to ensure that
// but this time, they don't say preorder array and inorder array will have same count nodes
if(i_preorderTraversal.size() != i_inorderTraversal.size() || i_preorderTraversal.empty()) return nullptr;
TreeNode *result = new TreeNode(i_preorderTraversal.front());
// the stack means parent nodes, which don't consider right child for now
stack<TreeNode*> nodesNotCheckRightChild{{result}};
for(int i = 1, index = 0; i < i_preorderTraversal.size(); i++)
{
int preorderValue = i_preorderTraversal[i];
TreeNode *node = nodesNotCheckRightChild.top();
// this case means the current node is the stack.top() node's left child
// since preorder is root->left->right, inorder is left->root->right
// if two secutive nodes A and B, B is A's right child, then A doesn't have left child
// in this case, two orders are root->right, so they must be equal
if(node->val != i_inorderTraversal[index])
{
node->left = new TreeNode(preorderValue);
nodesNotCheckRightChild.push(node->left);
}
else
{
// this case means left single branch, so two orders are reverse
while(!nodesNotCheckRightChild.empty() && nodesNotCheckRightChild.top()->val == i_inorderTraversal[index])
{
node = nodesNotCheckRightChild.top();
nodesNotCheckRightChild.pop();
index++;
}
node->right = new TreeNode(preorderValue);
nodesNotCheckRightChild.push(node->right);
}
}
return result;
}
};