持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情
题目:
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例 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
思路分析:
首先,我们要先知道前序遍历和中序遍历的遍历顺序。
二叉树前序遍历的顺序为:
1.先遍历根节点;
2.随后递归地遍历左子树;
3.最后递归地遍历右子树。
二叉树中序遍历的顺序为:
1.先递归地遍历左子树;
2.随后遍历根节点;
3.最后递归地遍历右子树。
方法:递归
递归建立整棵二叉树:先递归创建左右子树,然后创建根节点,并让指针指向两棵子树。
具体步骤如下:
- 先利用前序遍历找根节点:前序遍历的第一个数,就是根节点的值;
- 在中序遍历中找到根节点的位置i,则 i 左边是左子树的中序遍历,右边是右子树的中序遍历;
- 假设左子树的中序遍历的长度是 l,则在前序遍历中,根节点后面的 l个数,是左子树的前序遍历,剩下的数是右子树的前序遍历;
- 有了左右子树的前序遍历和中序遍历,我们可以先递归创建出左右子树,然后再创建根节点;
时间复杂度分析
如果通过遍历整个中序找到根节点进行定位,复杂度较高,所以我们在初始化时,用哈希表(unordered_map<int,int>)记录每个值在中序遍历中的位置,这样我们在递归到每个节点时,在中序遍历中查找根节点位置的操作,只需要 O(1) 的时间。此时,创建每个节点需要的时间是 O(1),所以总时间复杂度是 O(n)。
AC代码:
class Solution {
public:
vector<int> preorder, inorder;
map<int, int> mp;
TreeNode* buildTree(vector<int>& _preorder, vector<int>& _inorder) {
preorder = _preorder, inorder = _inorder;
for(int i = 0; i < inorder.size(); i ++ ){
mp[inorder[i]] = i;
}
return dfs(0, preorder.size() - 1, 0, inorder.size() - 1);
}
TreeNode* dfs(int pl, int pr, int il, int ir){
if(pl > pr) return NULL;
TreeNode* root = new TreeNode(preorder[pl]);
int p = mp[preorder[pl]];
root->left = dfs(pl + 1, pl + 1 + p - il - 1, il, p - 1);
root->right = dfs(pl + 1 + p - il - 1 + 1, pr, p + 1, ir);
return root;
}
};
来源:力扣(LeetCode)