Constructing binary tree from pre / mid / post traversal sequence
Basics
First of all, we need to know the specific order of the three depth first traversal binary trees:
- Preface: middle left and right
- Middle order: left middle right
- Post order: left and right middle
In addition, you should know that only middle order + pre / post order can uniquely determine a binary tree, while pre order + post order cannot uniquely determine a binary tree.
thinking
In the problem of constructing binary tree, we usually use the divide and conquer idea of recursive form to realize it. In the pre / post sequence, we know that the first / last element must be the root node. We take out the value of the root node and find the value of the node in the middle sequence (such problems usually ensure that there are no duplicate elements in the traversal sequence) and write down its index.
In the middle order sequence, the left and right sequences of the root node are the middle order sequences of its left and right subtrees respectively. We construct its left and right subtrees recursively, and finally get the complete tree.
105. Construct binary tree from preorder and inorder traversal sequences
Let's look at the characteristics of pre order and middle order. Pre order 1,2,4,7,3,5,6,8 and middle order 4,7,2,1,5,3,8,6;
The preorder / middle order traversal sequence required by the current tree to be constructed (possibly a sub tree of the whole) must be a sub sequence of the preorder / middle order traversal sequence of the whole tree. We use preleft, preright, inleft and inright to represent the starting position of the sub sequence in the overall preorder / middle order sequence respectively.
- The first 1 from the left in the preamble must be the root node. We can find the location of the root node in the preamble according to its value rootVal, and record it as mid;
- In the middle order, the left side of the root node is the left subtree node, and the right side is the right subtree node. That is [left subtree node, root node, right subtree node], we can get that the number of left subtree nodes is mid inleft;
- The node distribution in the preamble should be: [root node, left subtree node, right subtree node];
- According to the number of left subtrees determined in the previous step, the range of left subtree nodes and right subtree nodes in the preamble can be determined;
- If we want to generate a binary tree by preorder traversal, the next level of recursion should be:
- Left subtree: Root - > left = helper (preorder, inorder, left subtree preorder start point, left subtree preorder end point, left subtree middle order start point, left subtree middle order end point);
- Right subtree: Root - > right = helper (preorder, inorder, right subtree preorder start point, right subtree preorder end point, right subtree middle order start point, right subtree middle order end point);
- Each layer of recursion should return the current root node root;
All codes are as follows:
class Solution { private: TreeNode* helper(vector<int>& preorder, vector<int>& inorder, int preLeft, int preRight, int inLeft, int inRight) { if (inLeft >= inRight) return nullptr; int rootVal = preorder[preLeft]; int mid = inLeft; for (; mid<inRight; ++mid) if (inorder[mid] == rootVal) break; TreeNode* root = new TreeNode(rootVal); root->left = helper(preorder, inorder, preLeft+1, preLeft+1+mid-inLeft, inLeft, mid); root->right = helper(preorder, inorder, preLeft+1+mid-inLeft, preRight, mid+1, inRight); return root; } public: TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { return helper(preorder, inorder, 0, preorder.size(), 0, inorder.size()); } };
106. Construct binary tree from middle order and post order traversal sequences
It is similar to the construction of binary tree in pre order and middle order:
class Solution { private: TreeNode* helper(vector<int>& inorder, vector<int>& postorder, int inLeft, int inRight, int postLeft, int postRight) { if (inLeft >= inRight) return nullptr; int rootVal = postorder[postRight-1]; int mid = inLeft; for (; mid<inRight; ++mid) if (inorder[mid] == rootVal) break; TreeNode* root = new TreeNode(rootVal); root->left = helper(inorder, postorder, inLeft, mid, postLeft, postLeft+mid-inLeft); root->right = helper(inorder, postorder, mid+1, inRight, postLeft+mid-inLeft, postRight-1); return root; } public: TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { return helper(inorder, postorder, 0, inorder.size(), 0, postorder.size()); } };
889. Construct binary tree according to pre order and post order traversal
Note that we mentioned earlier that the pre order / post order sequence cannot uniquely determine a binary tree (in fact, the pre order and post order can uniquely determine a binary tree only when the degree of each node is 2 or 0). Therefore, the title description of this topic includes:
- Each input is guaranteed to have at least one answer. If there are multiple answers, you can return one of them.
class Solution { private: TreeNode* helper(vector<int>& preorder, vector<int>& postorder, int preLeft, int preRight, int postLeft, int postRight) { if (preLeft > preRight) return nullptr; int rootVal = preorder[preLeft]; TreeNode* root = new TreeNode(rootVal); if (preLeft == preRight) return root; int mid = 0; for (; mid<postRight; ++mid) if (postorder[mid] == preorder[preLeft+1]) break; root->left = helper(preorder, postorder, preLeft+1, preLeft+1+mid-postLeft, postLeft, mid); root->right = helper(preorder, postorder, preLeft+2+mid-postLeft, preRight, mid+1, postRight-1); return root; } public: TreeNode* constructFromPrePost(vector<int>& preorder, vector<int>& postorder) { return helper(preorder, postorder, 0, preorder.size()-1, 0, postorder.size()-1); } };