根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
我的思路
其实就是模仿正常人分析的根据前序遍历和中序遍历还原二叉树。
以下面的树举个例子
1,2,4,7,3,5,6,8 //前序
4,7,2,1,5,3,8,6 //中序
首先找到前序遍历的第一个数1,必然是根节点,然后我们接着看中序遍历1的位置,中序遍历1的左边是472,说明这棵树1的左子树部分就是472,但是根是哪个数,还需要继续判定,接着我们找到前序遍历1的右边247,因为前序遍历是根左右嘛,根的右边有一部分是左子树,然后把上面中序遍历的472和前序遍历的247截取出来(我这里使用递归),继续判断,按照我上面说的规则,前序遍历的2自然是根节点,也是1的左子树。右子树同理。
其实代码不难,也不长,理解起来就好了。
代码:
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (preorder.size() != inorder.size() || preorder.size() == 0)//size等于正常,没有节点了
//但是中序遍历的size,也就是长度跟前序遍历的长度不相等,说明这棵数有问题(不存在)
//不过LeetCode保证树不会出问题,加了上面判断条件可能会变慢,但是正常程序来讲,还是得判断异常
{
return NULL;
}
int index = -1;
for (int i = 0; i < preorder.size(); ++i)
{
if (inorder[i] == preorder[0])//找到中序遍历根节点的位置
{
index = i;
break;
}
}
if (index == -1)//没找到根节点,说明有问题
{
return NULL;
}
TreeNode *root = new TreeNode(preorder[0]);//当前根节点
vector<int> lchildpre(preorder.begin() + 1, preorder.begin() + 1 + index);//左子树前序遍历
vector<int> lchildin(inorder.begin(), inorder.begin() + index);//左子树中序遍历
root->left = buildTree(lchildpre, lchildin);//左子树
vector<int> rchildpre(preorder.begin() + 1 + index, preorder.end());//右子树前序遍历
vector<int> rchildin(inorder.begin() + 1 + index, inorder.end());//右子树中序遍历
root->right = buildTree(rchildpre, rchildin);//右子树
return root;//返回当前根节点
}
};