题目:105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
某二叉树的先序遍历结果记录于整数数组 preorder
,它的中序遍历结果记录于整数数组 inorder
。请根据 preorder
和 inorder
的提示构造出这棵二叉树并返回其根节点。
注意:preorder
和 inorder
中均不含重复数字。
题解:
【1】一个二叉树的前序遍历数组的第一个元素一定是二叉树的根节点;
【2】在中序遍历中,根节点前面的元素都在左子树,根节点后面的元素都在右子树
因此,可以递归地构建二叉树,在每个递归循环内:
前序遍历的第一个元素是根节点(node->val = 前序遍历的第一个元素),在终须遍历中找到其位置i;
将中序遍历中i前面的元素作为新的左子树的中序遍历数组,前序遍历从[1, i]的元素作为左子树的前序遍历数组,递归地建立左子树;
自身node->lelt = 左子树的根节点;
将中序遍历中i后面的元素作为新的右子树的中序遍历数组,前序遍历[i+1, end]的元素作为 右子树的前序遍历,递归地建立右子树;
自身node->right = 右子树的根节点;
终止条件:前序遍历的元素个数为0(也是中序遍历元素的个数为0)return nullptr;
代码:
class Solution {
public:
int pos_in_inorder(int val, vector<int>& b) {
for (int i = 0; i < b.size(); ++i) {
if (b[i] == val)
return i;
}
return -1;
}
TreeNode* deduceTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size()==0) return nullptr;
assert(preorder.size() == inorder.size());
assert(preorder.size() > 0);
int val = preorder[0];
int i = pos_in_inorder(val, inorder);
struct TreeNode* treenode = new struct TreeNode(val);
vector<int> a_left(preorder.begin() + 1, preorder.begin() + i + 1);
vector<int> b_left(inorder.begin(), inorder.begin() + i);
treenode->left = deduceTree(a_left, b_left);
vector<int> a_right(preorder.begin()+i+1, preorder.end());
vector<int> b_right(inorder.begin()+i+1, inorder.end());
treenode->right = deduceTree(a_right, b_right);
return treenode;
}
};
优化;可以用哈希表O(N)时间复杂度to get i
有什么好的想法与问题欢迎交流~