题目链接:105. 从前序与中序遍历序列构造二叉树

题解:

二叉树的前中序构造二叉树!

题目简述:

给定二叉树的前中序遍历来构造一颗二叉树!

题解:

必会知识:

  • 前序遍历的第一个节点一定是根节点
  • 中序遍历可以借助前序遍历得到的根节点将区间分为左右子树两部分
  • 看明白了吧,按照左右子树区间进行递归即可!

思路:

  • 由于我们要从中序遍历找前序遍历得到的根节点,所以事先将中序遍历的节点和下标关系存储于哈希表,使得可以在O(1)时间查询到下标
  • 根节点:前序遍历的第一个节点,root = new TreeNode(preorder[pl])
  • 当没有节点时即pl > pr,返回NULL
  • TreeNode* build(vector<int>& preorder, vector<int>& inorder, int pl, int pr, int il, int ir),参数分别为:前序,中序,前序起始下标,前序终止下标,中序起始下标,中序终止下标
  • k为中序遍历根节点下标,创建一个根节点,左右子树递归得到
  • 左子树下标: pl + 1, k - 1 - il + pl + 1, il, k - 1
  • 右子树下标:k - 1 - il + pl + 1 + 1, pr, k + 1, ir
  • 下标计算见下图:

时间复杂度:由于哈希表的应用使得复杂度降到了O(n)

AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 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> pos;
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
for(int i = 0; i < inorder.size(); i++) pos[inorder[i]] = i;
return build(preorder, inorder, 0, preorder.size() - 1, 0, inorder.size() - 1);
}
TreeNode* build(vector<int>& preorder, vector<int>& inorder, int pl, int pr, int il, int ir){
if(pl > pr) return NULL;
auto root = new TreeNode(preorder[pl]);
int k = pos[root->val];
root->left = build(preorder, inorder, pl + 1, k - 1 - il + pl + 1, il, k - 1);
root->right = build(preorder, inorder, k - 1 - il + pl + 1 + 1, pr, k + 1, ir);
return root;
}
};