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;    }};

0 0
原创粉丝点击