题目:
Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
题意:
根据给定的前序遍历与中序遍历构造二叉树
note:
可以假设在二叉树中没有重复元素
思路一:递归实现。根据前序遍历可以确定根元素,由根元素与中序遍历可以判断出左右子树分别为什么。
例子:前序遍历序列:1 2 4 5 3 6 7
中序遍历序列:4 2 51 6 3 7
后序遍历序列:4 5 2 6 7 3 1
代码:60ms 比较好理解
/** * 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(begin(preorder), end(preorder), begin(inorder), end(inorder)); } template<typename InputIterator> TreeNode* buildTree(InputIterator pre_first, InputIterator pre_last, InputIterator in_first, InputIterator in_last){ if(pre_first == pre_last){ return nullptr; } if(in_first == in_last){ return nullptr; } auto root = new TreeNode(*pre_first); //创建节点 auto RootPos = find(in_first, in_last, *pre_first); //在中序遍历中找到根元素的位置 auto leftSize = distance(in_first, RootPos); //利用中序遍历找到左子树的长度 root->left = buildTree(next(pre_first), next(pre_first, leftSize+1), in_first, next(in_first, leftSize)); //根据找到的左子树的前序与中序遍历部分构建左子树 root->right = buildTree(next(pre_first, leftSize+1), pre_last, next(RootPos), in_last); //根据找到的右子树的前序与中序遍历部分构建右子树 return root; } };思路二:
利用堆栈实现。将前序遍历的元素且不与中序遍历第一个元素相同的元素压入堆栈中,当栈顶元素与中序遍历数组值相等时,切换到右子树,并弹出栈顶元素值。
代码:12ms 时间复杂度最低
/** * 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) { if(preorder.empty()){ return NULL; } TreeNode* root = new TreeNode(preorder[0]); TreeNode* cur = root; stack<TreeNode*> stacks; //利用堆栈实现,先构建左子树,后构建右子树 stacks.push(root); int flag = 0; //切换左右子树 int pre_index = 1; //前序遍历数组下标 int in_index = 0; //中序遍历数组下标 while(in_index < inorder.size()){ if(!stacks.empty() && stacks.top()->val == inorder[in_index]){ //将栈顶元素与中序遍历元素相比较,相同则弹出 cur = stacks.top(); flag = 1; stacks.pop(); ++in_index; //中序遍历下标后移 }else{ TreeNode* tmp = new TreeNode(preorder[pre_index]); //创建新的节点 if(flag == 0){ cur->left = tmp; //将新创建的节点添加到左子树 cur = cur->left; }else{ cur->right = tmp; //将新创建的节点添加到右子树 cur = cur->right; flag = 0; } stacks.push(tmp); //将前序遍历中与中序遍历不相同的元素放入堆栈中。 ++pre_index; //前序遍历数组下标后移 } } return root; } };