输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
限制:
0 <= 节点个数 <= 5000
大概思路:
二叉树的前序遍历顺序是:根节点、左子树、右子树,每个子树的遍历顺序同样满足前序遍历顺序。二叉树的中序遍历顺序是:左子树、根节点、右子树,每个子树的遍历顺序同样满足中序遍历顺序。所以根据前序遍历得知前面的就是跟节点,根据这个根节点在中序遍历中就可以确定左子树和右子树。例如:3在preorder的第一个,那么他就是根节点,所以在中序遍历inorder中[9]就是左子树,[15,20,7]就是右子树。层层递归就能得到最终的二叉树
代码实现:
一,
/**
* 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* buildTreeCode(vector<int>&preorder, int prestart, int preend, vector<int>& inorder, int inostart, int inoend)
{
if (prestart>preend || inostart > inoend)
{
return nullptr;
}
TreeNode *root = new TreeNode(preorder[prestart]);
for (auto i = inostart; i <= inoend; i++)
{
if (preorder[prestart] == inorder[i])
{
root->left = buildTreeCode(
preorder, prestart + 1, i - inostart + prestart,
inorder, inostart, i - 1);
//在前序排列中root就是prestart,所以prestart不在区间内
root->right = buildTreeCode(
preorder, i - inostart + prestart + 1, preend,
inorder, i + 1, inoend);
//在中序排列中第I个就是root所以在区间内不包括i
break;
}
}
return root;
}
TreeNode* buildTree(vector<int> &preorder, vector<int>&inorder) {
if (preorder.empty() || inorder.empty())
{
return nullptr;
}
return buildTreeCode(
preorder, 0, preorder.size() - 1,
inorder, 0, inorder.size() - 1);
}
};
注意:这个的取值空间的闭的,所以每次都将root节点都不在取值空间内,而且size()-1也是为了取到最后一个元素,保证是一个闭区间。
二,收到力扣题解的思路,在其中加入的迭代器。
class Solution {
public:
TreeNode* buildTreeCode(
vector<int>::iterator preBegin,
vector<int>::iterator preEnd,
vector<int>::iterator inBegin,
vector<int>::iterator inEnd)
{
if (inBegin == inEnd)
{
return nullptr;
}
TreeNode*cur = new TreeNode(*preBegin);
auto root = find(inBegin, inEnd, *preBegin);
cur->left = buildTreeCode(
preBegin + 1, preBegin + 1 + (root - inBegin),
inBegin, root);
//区间是左闭右开
cur->right = buildTreeCode(
preBegin + 1 + (root - inBegin), preEnd,
root + 1, inEnd);
return cur;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (preorder.empty() || inorder.empty())
{
return nullptr;
}
return buildTreeCode(preorder.begin(), preorder.end(),
inorder.begin(), inorder.end());
}
};
注:迭代器end是指向性最后这个元素的下一个,所以这个的取值区间是左闭右开的。
这个题的最麻烦的就是确定取值区间,一定要先确定自己的取值区间是什么样的,这样带递归的时候才不会出错