输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例 1:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
示例 2:Input: preorder = [-1], inorder = [-1]
Output: [-1]限制:
0 <= 节点个数 <= 5000
方法一:递归法
代码语言:cpp
/**
* 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:
unordered_map<int, int> index;
TreeNode* myBuildTree(vector<int>& preorder, vector<int>& inorder, int preorder_start, int preorder_end, int inorder_start, int inorder_end){
if(preorder_start > preorder_end)
return nullptr;
int preorder_root = preorder_start; // 前序遍历中的第一个节点就是根节点
int inorder_root = index[preorder[preorder_root]]; // 在中序遍历中定位根节点
TreeNode* root = new TreeNode(preorder[preorder_root]); // 先把根节点建立出来
root->left = myBuildTree(preorder, inorder, preorder_start + 1, preorder_start + inorder_root - inorder_start, inorder_start, inorder_root - 1); // 递归地构造左子树,并连接到根节点,先:从左边界+1 开始的inorder_root - inorder_start 个元素,中:从左边界开始到根节点定位-1个元素
root->right = myBuildTree(preorder, inorder, preorder_start + inorder_root - inorder_start + 1, preorder_end, inorder_root + 1, inorder_end); // 递归地构造右子树,并连接到根节点,先:从 左边界+1+左子树节点数目开始到右边界的元素,中:从根节点定位+1到右边界的元素
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int length = preorder.size(); //结点个数
for(int i=0;i<length;i++) // 构造哈希集合,帮助我们快速定位根节点
index[inorder[i]] = i;
return myBuildTree(preorder, inorder, 0, length - 1, 0, length - 1);
}
};
203 / 203 个通过测试用例
状态:通过
执行用时: 8 ms
内存消耗: 24.9 MB
方法二:迭代法
代码语言:cpp
/**
* 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* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(!preorder.size()){ //判断是否为空
return nullptr;
}
TreeNode* root = new TreeNode(preorder[0]); //先序的首为根节点
stack<TreeNode*> stk; //建立栈
stk.push(root); //根节点入栈
int inorderIndex = 0; //扫描中序的指针
for(int i = 1; i < preorder.size(); i++){ //从先序遍历开始逐个遍历
TreeNode *node = stk.top();
if(node->val != inorder[inorderIndex]){ //栈顶元素的值与中序遍历当前所指的元素值不等
node->left = new TreeNode(preorder[i]); //前序遍历中处在栈顶元素位置后一位的元素是栈顶元素的左子树
stk.push(node->left); //栈顶元素左子树节点入栈
}else{ //栈顶元素的值与中序遍历当前所指的元素值相等,栈顶即为最左下角的树节点
while(!stk.empty() && stk.top()->val == inorder[inorderIndex]){ //while循环向上返回,寻找位置进行右子树的重建
node = stk.top(); //指针向右扫描中序遍历
stk.pop(); //栈中所有与当前指针所指元素值相等的节点出栈
inorderIndex++;
}
node->right = new TreeNode(preorder[i]); // 循环结束后,node所指栈顶元素即是需要重建右子树的节点
stk.push(node->right);
}
}
return root;
}
};
203 / 203 个通过测试用例
状态:通过
执行用时: 8 ms
内存消耗: 23.4 MB