LeetCode_Construct Binary Tree from Preorder and Inorder Traversal
来源:互联网 发布:ftp 21端口 编辑:程序博客网 时间:2024/06/06 05:35
Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
题目如上所示:给出二叉树的先序遍历序列和中序遍历序列,复原二叉树。
分析:
1)题目拿过来,首先要清楚二叉树的三种遍历方式:
前序遍历(Preorder),首先访问根节点,然后遍历左子树,最后遍历右子树(根-左-右)
中序遍历(inorder),首先遍历左子树,然后访问根节点,最后遍历右子树(左-根-右)
后序遍历(postorder),首先遍历左子树,然后遍历右子树,最后访问根节点(左-右-根)
可见,二叉树的三种遍历方式是从根节点角度来看的,其遍历方法可以查看算法导论,如果没记错的话是采用涂色(黑、白、灰)的方法实现遍历的。
现举一例:
上图中的二叉树遍历:
先序:ABDCEFGH
中序:BDAFEHGC
后序:DBFHGECA
2)现在回归到问题本身,给出先序序列和中序序列,要复原二叉树,为了分析方便我们仍以上图中树形为例:
12345678
先序 ABDCEFGH
中序 BDAFEHGC
根据先序序列,可以知道A为整棵树的根(先序序列第一个节点为整棵树的根),由此可以通过对中序序列进行扫描得到:
左子树的中序:BD
右子树的中序:FEHGC
另外一点我们知道,先序序列与中序序列的长度肯定是相同的,那么由此,我们又可以得到
左子树的先序:BD
右子树的先序:CEFGH
这样我们将一个大的问题划分为两个小问题,即要想复原一棵树,只需复原其根的左子树和右子树即可,由此可以采用递归的方法(其实树的问题大多都可以使用递归)
3)确定的递归方法之后,要找出递归出口,经过分析,这个问题的递归出口很简单:
a.先序(中序)序列中只有一个元素时,那么树种只有一个节点,直接返回
b.先序(中序)序列中没有元素的,空树,返回NULL。
由此得出以下代码:
// Definition for binary tree 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) {vector<int>::iterator iter;//递归出口if (preorder.empty()){return NULL;}if (preorder.size()==1){ TreeNode * root=new TreeNode(preorder[0]); return root;}//根据先序序列构造整棵树的根节点 TreeNode * root=new TreeNode(preorder[0]);//获取根节点在中序序列中的位置,同时分解中序序列为“左子树”和“右子树”int pos=0;vector <int> leftInorder;vector <int> rightInorder;for (iter=inorder.begin();iter<inorder.end();iter++){if (*iter==root->val){break;}leftInorder.push_back(*iter);pos++;}pos++;for (iter=inorder.begin()+pos;iter<inorder.end();iter++){rightInorder.push_back(*iter);}//递归求解vector <int> leftPreorder;vector <int> rightPreorder;for (iter=preorder.begin()+1;iter<preorder.begin()+pos;iter++){leftPreorder.push_back(*iter);}for (;iter<preorder.end();iter++){rightPreorder.push_back(*iter);}root->left=buildTree(leftPreorder,leftInorder);root->right=buildTree(rightPreorder,rightInorder);return root; }};
提交,发现Memory Limited Exceeded!原因就在于递归中申请了太多空间,其实经过仔细分析,题目中给出的函数入口格式并不好,因为我们没有必要为先序和中序序列申请新的空间(算法中并不改变序列本身),为此自定义一个函数格式,代码如下
// Definition for binary tree 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) {//vector<int>::iterator iter;////递归出口//if (preorder.empty())//{//return NULL;//}//if (preorder.size()==1)//{// TreeNode * root=new TreeNode(preorder[0]);// return root;//}////根据先序序列构造整棵树的根节点 // TreeNode * root=new TreeNode(preorder[0]);////获取根节点在中序序列中的位置,同时分解中序序列为“左子树”和“右子树”//int pos=0;//vector <int> leftInorder;//vector <int> rightInorder;//for (iter=inorder.begin();iter<inorder.end();iter++)//{//if (*iter==root->val)//{//break;//}//leftInorder.push_back(*iter);//pos++;//}//pos++;//for (iter=inorder.begin()+pos;iter<inorder.end();iter++)//{//rightInorder.push_back(*iter);//}//////递归求解//vector <int> leftPreorder;//vector <int> rightPreorder;//for (iter=preorder.begin()+1;iter<preorder.begin()+pos;iter++)//{//leftPreorder.push_back(*iter);//}//for (;iter<preorder.end();iter++)//{//rightPreorder.push_back(*iter);//}//root->left=buildTree(leftPreorder,leftInorder);//root->right=buildTree(rightPreorder,rightInorder);//return root; return build(preorder,inorder,0,0,preorder.size()); } TreeNode* build(vector<int> &preorder, vector<int> &inorder,int prestart, int instart,int seqLen) { vector<int>::iterator iter; /* cout<<"========================="<<endl; cout<<"Prestart:"<<prestart<<endl; cout<<"InStart:"<<instart<<endl; cout<<"seqLen"<<seqLen<<endl; for (iter=preorder.begin()+prestart;iter<preorder.begin()+prestart+seqLen;iter++) { cout<<*iter<<" "; } cout<<endl;*//*for (iter=inorder.begin()+instart;iter<inorder.begin()+instart+seqLen;iter++){cout<<*iter<<" ";}cout<<endl;*///递归出口if (seqLen==0){return NULL;}if (seqLen==1){ TreeNode * root=new TreeNode(preorder[prestart]); return root;}//根据先序序列构造整棵树的根节点 TreeNode * root=new TreeNode(preorder[prestart]);//获取根节点在中序序列中的位置,同时分解中序序列为“左子树”和“右子树”的起点和长度int leftLen=0;//左子树长度int rightLen=0;//右子树长度for (iter=(inorder.begin()+instart);iter<(inorder.begin()+instart+seqLen);iter++){if (*iter==root->val){break;}leftLen++;}/*leftLen++;*/for (iter=(inorder.begin()+instart+leftLen+1);iter<(inorder.begin()+instart+seqLen);iter++){rightLen++;}root->left=build(preorder,inorder,prestart+1,instart,leftLen);root->right=build(preorder,inorder,(prestart+leftLen+1),(instart+leftLen+1),rightLen);return root; }};
- *Leetcode_construct-binary-tree-from-preorder-and-inorder-traversal
- LeetCode_Construct Binary Tree from Preorder and Inorder Traversal
- LeetCode_Construct Binary Tree from Preorder and Inorder Traversal
- *Leetcode_construct-binary-tree-from-inorder-and-postorder-traversal
- Leetcode_Construct Binary Tree from Inorder and Postorder Traversal
- LeetCode_Construct Binary Tree from Inorder and Postorder Traversal
- *(leetcode) Construct Binary Tree from Preorder and Inorder Traversal (tree)
- LeetCode[Tree]: Construct Binary Tree from Preorder and Inorder Traversal
- [leetcode][tree] Construct Binary Tree from Preorder and Inorder Traversal
- Construct Binary Tree from Preorder and Inorder Traversal & Construct Binary Tree from Inorder and P
- LeetCode: Construct Binary Tree from Preorder and Inorder Traversal
- Construct Binary Tree from Preorder and Inorder Traversal
- [LeetCode]Construct Binary Tree from Preorder and Inorder Traversal
- LeetCode Construct Binary Tree from Preorder and Inorder Traversal
- [Leetcode] Construct Binary Tree from Preorder and Inorder Traversal
- Leetcode: Construct Binary Tree from Preorder and Inorder Traversal
- [LeetCode] Construct Binary Tree from Preorder and Inorder Traversal
- LeetCode Construct Binary Tree from Preorder and Inorder Traversal
- 用VMware安装虚拟系统时出现Invalid system disk,Replace the disk and then press any key
- OpenCv学习笔记(二)—cv::Mat学习
- HDU 2955 Robberies
- 虚拟机中linux系统的网络设置
- 黑马程序员_新的数据类型block
- LeetCode_Construct Binary Tree from Preorder and Inorder Traversal
- 细说socket函数
- 网站访问量的统计(Application和Session应用)
- Ubuntu14.04创建桌面快捷方式
- java 中类的加载顺序
- VS2013使用SQL2012数据库介绍
- main函数两个参数用法(转)
- 多数用户仍用老款iPhone 有望迎升级热潮
- Java高级视频_网络编程