题目
给定一棵树的前序遍历 preorder 与中序遍历 inorder。请构造二叉树并返回其根节点。
示例 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]
- 方法一:递归
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
unordered_map<int, int> index;//储存中序遍历序列中每个节点元素所对应的下标
public:
//传入六个参数
//前序遍历序列,中序遍历序列,前序遍历序列的最左节点,前序遍历序列的最有节点,中序遍历序列的最左节点,中序遍历序列的最右节点
TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder, int preleft, int preright, int inleft, int inright){
//递归出口
if(preleft >preright) return NULL;
//前序遍历序列的第一个节点就是根节点
//用根节点查找哈希表找到中序遍历序列中的位置,该节点将中序遍历序列划分为两部分,分别是左子树和右子树
int preroot = preleft;
int inroot = index[preorder[preroot]];
//建立根节点
TreeNode *root = new TreeNode(preorder[preroot]);
int left_subtree_size = inroot - inleft;//计算左子树的节点数目
//递归调用得到左子树和右子树
root->left = myBuildTree(preorder, inorder, preleft+1,preleft+left_subtree_size,inleft,inroot-1);
root->right = myBuildTree(preorder, inorder, preleft+left_subtree_size+1, preright, inroot+1,inright);
return root;
}
//建立哈希表储存中序遍历序列中每个节点的值所对应的下标
//递归调用建树函数建立二叉树
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n = preorder.size();
for(int i=0; i<n; i++)
index[inorder[i]] = i;
return myBuildTree(preorder, inorder, 0, n-1, 0, n-1);
}
};
- 时间复杂度O(n)
- 空间复杂度O(n)
- 思路
- 先建立根节点,再递归调用建立其左右子树
- 前序遍历序列的第一个节点为根节点的元素,根据该元素查找哈希表找到中序遍历序列中的位置,该位置将中序遍历序列划分为两部分,左边的为左子树,右边的为右子树。建立根节点,它的左孩子指向递归调用建立左子树的返回值,它的右孩子指向递归调用建立右子树的返回值。