Today's shared content is also a combination of two questions in leetcode. You can clear your mind and go to the platform to do some questions and test the results.
First of all, we have to understand the characteristics of three ergodic ways:
Preorder: in preorder traversal, first traverse root, that is to say, the first element in the preorder sequence is the root node of the original binary tree.
In the same way, in the postmaster, the last element in the sequence that traverses left & right first is the root node of the binary tree.
The feature of inorder is: left root right, so if we find the root node in it, we can directly separate the sequence corresponding to the left subtree and the right subtree.
Then we transform the problem of building the original binary tree into the construction of left and right subtrees, and so on, we can continuously reduce the problem, and finally integrate it.
Description of binary tree:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */
Take one of them as an example. I μ L, I μ r represent the left and right endpoints of the sequence, P μ L, P μ r represent the left and right endpoints of the sequence, and index represent the subscript position of the root node in the sequence.
in: [i_l, index - 1, index, index + 1, i_r]
pre: [root, p_l + 1, p_l + len, p_l + len + 1, p_r]
Where len = index - i_l = = length of left subtree.
The binary tree is constructed from the middle order and the preorder traversal sequences.
class Solution { public: // Recursive call + divide and conquer TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { if(preorder.size() == 0) return NULL; return helper(preorder, 0, preorder.size() - 1, inorder, 0, inorder.size() - 1); } TreeNode* helper(vector<int> &preorder, int p_l, int p_r, vector<int> &inorder, int i_l, int i_r){ if(p_l > p_r || i_l > i_r) return NULL; TreeNode* root = new TreeNode(preorder[p_l]); int index = find(inorder, preorder[p_l]);//The location of the root node in the middle order sequence if(index == -1) return NULL; int len = index - i_l; //Calculate the length of the left subtree root->left = helper(preorder, p_l + 1, p_l + len, inorder, i_l, index - 1); root->right = helper(preorder, p_l + len + 1, p_r, inorder, index + 1, i_r); return root; } int find(vector<int> v, int target){ if(v.size() == 0) return -1; for(int i = 0; i < v.size(); i ++){ if(v[i] == target) return i;// Return subscript } return -1; } };
According to the middle order and the post order traversal sequence, a binary tree is constructed.
class Solution { public: TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { if(inorder.size() == 0) return NULL; return helper(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1); } TreeNode* helper(vector<int> &inorder, int i_l, int i_r, vector<int> &postorder, int po_l, int po_r){ if(i_l > i_r || po_l > po_r) return NULL; TreeNode* root = new TreeNode(postorder[po_r]);//Take the last node value int index = find(inorder, postorder[po_r]); if(index == -1) return NULL; int len = index - i_l; //Calculate the length of the left subtree root->left = helper(inorder, i_l, index - 1, postorder, po_l, po_l + len - 1); root->right = helper(inorder, index + 1, i_r, postorder, po_l + len, po_r - 1); return root; } int find(vector<int> v, int target){ if(v.size() == 0) return -1; for(int i = 0; i < v.size(); i ++){ if(v[i] == target) return i;// Return subscript } return -1; } };
Thinking: but in these two questions, we can consider to record the relationship between the subscript of the elements in the middle order sequence and the corresponding number, so as to improve the search speed, instead of finding () every time.