您的位置:首页 > 其它

从前序与中序遍历序列构造二叉树

2020-01-14 09:27 267 查看

  进入来看我这篇文章的小伙伴应该大都是遇见了leetcode中的105. 从前序与中序遍历序列构造二叉树或是106. 从中序与后序遍历序列构造二叉树,其实这两个题是明显的同意思路,如果一个题目没有思路,可以看看别人的解答,然后把另外一个当作练习,这也是极好的。

原理讲解


  这两个题目的思路其实是和之前遍历二叉树的思路是一样的:分而治之
  在这样一个题目中,第一个重要的思路是前序(后序)在vector中的第一个值(最后一个值)是对应的一个父节点。

以下给出leetcode中的例子来帮助说明:


不得不提的是这个题目有这样一个假设:你可以假设树中没有重复的元素。所以以下我会用数字代指节点。

  1. 在刚拿到这个题目时,我们可以根据前序vector得出判断:3是一个父节点(如果无法理解这一步的话,我们需要复习一下先序遍历)。
  2. 根据1的结论,我们再由中序队列得出3这个节点的左边是[9],右边是[15,20,7](如果无法理解这一步的话,我们需要复习一下中序遍历)。
  3. 由2的结论,我们能够知道3这个节点左边的节点有1个,右边有3个。由此得到在前序的情况下:3这个节点左边是[9],右边是[20,15,7]。

=> 到这里我们得到了:

前序:[9]    前序:[20,15,7]
中序:[9]   中序: [15,20,7]

  又回到了题目类似的条件。再如此循环,直到为空便可得出结果。

106. 从中序与后序遍历序列构造二叉树:源码

/**
* 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>& inorder, vector<int>& postorder) {
if(!inorder.size()) return nullptr;
root = new TreeNode(NULL);
_computeNode(inorder, postorder, root);
return root;
}
private:
void _computeNode(vector<int> inorder, vector<int> postorder, TreeNode* node) {
if(inorder.size() == 0) {
return;
} else if (inorder.size() == 1) {
node->val = inorder.back();
return ;
} else {
int cur = postorder.back();
node->val = cur;
auto iter = find(inorder.begin(), inorder.end(), cur);
if(iter == inorder.end()) return ;
int rsize = inorder.end() - iter - 1;
int lsize = iter - inorder.begin();
vector<int> lv = vector<int>(inorder.begin(), iter);
vector<int> rv =vector<int>(iter + 1, inorder.end());
if(lv.size()) {
node->left = new TreeNode(NULL);
_computeNode(lv, vector<int>(postorder.begin(), postorder.begin() + lsize), node->left);
}
if(rv.size()) {
node->right = new TreeNode(NULL);
_computeNode(rv, vector<int>(postorder.end() - 1 - rsize, postorder.end() - 1), node->right);
}
}
}
TreeNode* root;
};

——————

105. 从前序与中序遍历序列构造二叉树:源码

/**
* 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.size())
return nullptr;
root = new TreeNode(NULL);
_buildTree(preorder.begin(), preorder.end(), inorder.begin(), inorder.end(), root);
return root;
}
private:
TreeNode* root;
void _buildTree(vector<int>::iterator preBegin, vector<int>::iterator preEnd,
vector<int>::iterator inBegin, vector<int>::iterator inEnd, TreeNode* node)
{
if(preEnd - preBegin == 0) return ;
else if(preEnd - preBegin == 1)
{
node->val = *preBegin;
return ;
}else {
int cur = *preBegin;
node->val = cur;
auto iter = find(inBegin, inEnd, cur);
if(iter == inEnd) return ;
int lsize = iter - inBegin;
int rsize = inEnd - iter - 1;
if(lsize)
{
node->left = new TreeNode(NULL);
_buildTree(preBegin + 1, preBegin + lsize + 1, inBegin, iter, node->left);
}
if(rsize) {
node->right = new TreeNode(NULL);
_buildTree(preBegin + lsize + 1, preEnd, iter + 1, inEnd, node->right);
}
}
}
};


总结

  在106这个题目中,我用的是vector拷贝复制,性能消耗很大,但贵在思路看着更加清晰,跑起来88ms,比一些python的解决方案还要慢。在105这个题目中,我改正了这个错误,改用迭代器,28ms左右。可见拷贝这一行为的性能消耗之大,谨记。

  • 点赞
  • 收藏
  • 分享
  • 文章举报
两天宇宙人 发布了42 篇原创文章 · 获赞 0 · 访问量 2047 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐