原题:
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3 / \ 9 20 / \ 15 7
解答:
这个题目也是剑指offer中的一道题目,思路比较清晰,就是先序遍历的第一个元素rootValue是根元素,然后去中序遍历的序列中找到rootValue的位置,就可以把中序遍历序列中的元素分为左右两部分,左边是左子树上的元素,右边是右子树上的元素,然后分别对左右两边进行递归调用函数,最后返回根结点,就是答案了。
代码:
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
TreeNode* buildTree(vector<int>& preorder, int pLeft, int pRight,
vector<int>& inorder, int iLeft, int iRight)
{
if (preorder.empty())//如果序列为空
return nullptr;
if (pLeft == pRight)//如果只有一个元素
{
TreeNode *item = new TreeNode(preorder[pLeft]);
item->left = nullptr;
item->right = nullptr;
return item;
}
int key = preorder[pLeft];
int index = iLeft;
for (int i = iLeft; i <= iRight; i++)
{
if (inorder[i] == key)
{
index = i;
break;
}
}
TreeNode *root = new TreeNode(key);
if(index>iLeft)//左边有元素
root->left = buildTree(preorder, pLeft + 1, pLeft + index - iLeft, inorder,
iLeft, index - 1);
if(index<iRight)//右边有元素
root->right = buildTree(preorder, pLeft + index - iLeft + 1, pRight, inorder,
index + 1, iRight);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
return buildTree(preorder, 0, preorder.size() - 1, inorder, 0, inorder.size() - 1);
}
需要注意的是,原题给的函数是只有前序和后序两个序列作为输入的,因为我们需要知道要构造二叉树的元素的位置,所以需要分别加上范围,然后再进行编码。递归函数要注意出口的判断条件,在构造左右子树时也要判断是否有元素存在。