您的位置:首页 > 其它

每天一道LeetCode-----根据先序遍历和中序遍历还原二叉树

2017-12-29 14:04 393 查看

Construct Binary Tree from Preorder and Inorder Traversal

原题链接Construct Binary Tree from Preorder and Inorder Traversal



给定一个二叉树的先序遍历和中序遍历,要求重现这棵二叉树

另先序遍历的序列为preorder,中序遍历的序列为inorder,节点个数为n

根据先序遍历的特点,可知preorder[0]一定是整棵二叉树的根节点,那么,如果已确定根节点值在中序遍历序列inorder中的下标是i,就一定有

inorder[0 : i - 1]这些值属于根节点的左子树

inorder[i + 1, n - 1]这些值属于根节点的右子树

因为中序遍历是从最左边开始遍历,所以当遍历到根节点inorder[i]时,之前遍历到的节点一定都属于左子树

那么现在的目的就是如何确定左右子树的根节点,由先序遍历可知

preorder[0 + 1]一定是左子树的根节点

preorder[0 + 1 + (i - 0)]一定是右子树的根节点

因为先序遍历遍历到的节点顺序是从根节点到最左边,再到右边,那么既然已经直到左子树上有多少节点了(i - 0个),那么就可以确定右子树的根节点

直接递归即可

/**
* 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* buildTree(vector<int>& preorder, vector<int>& inorder) {
return buildTree(0, 0, inorder.size() - 1, preorder, inorder);
}
private:
/* preStart : 当前根节点在preorder中的下标
* [inStart:inEnd]  : 以preorder[preStart]为根节点的子树的节点值在inorder的范围
*/
TreeNode* buildTree(int preStart, int inStart, int inEnd, vector<int>& preorder, vector<int>& inorder)
{
if(preStart >= preorder.size() || inStart > inEnd)
return nullptr;

/* 申请根节点 */
TreeNode* root = new TreeNode(preorder[preStart]);
/* 寻找根节点在inorder的位置,拆分左右子树 */
int inIndex = 0;
for(int i = inStart; i <= inEnd; ++i)
{
if(inorder[i] == preorder[preStart])
{
inIndex = i;
break;
}
}

root->left = buildTree(preStart + 1, inStart, inIndex - 1, preorder, inorder);
root->right = buildTree(preStart + 1 + inIndex - inStart, inIndex + 1, inEnd, preorder, inorder);
return root;
}
};


本题主要需要弄清楚如何进行递归,当然拆分成左右子树是个很好的方法,不够不太容易想到。

先序遍历可以直到根节点,而中序遍历可以确定该根节点的左右子树的取值范围,从而不断拆分下去,最终求解
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode
相关文章推荐