LeetCode105 从前序和中序序列构造二叉树
题目描述:
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3 / \ 9 20 / \ 15 7
/** * 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(preorder, 0, preorder.size() - 1, inorder, 0, inorder.size() - 1); } TreeNode *buildTree(vector<int> &preorder, int pLeft, int pRight, vector<int> &inorder, int iLeft, int iRight) { if (pLeft > pRight || iLeft > iRight) return NULL; int i = 0; for (i = iLeft; i <= iRight; ++i) { if (preorder[pLeft] == inorder[i]) break; } TreeNode *cur = new TreeNode(preorder[pLeft]); cur->left = buildTree(preorder, pLeft + 1, pLeft + i - iLeft, inorder, iLeft, i - 1); cur->right = buildTree(preorder, pLeft + i - iLeft + 1, pRight, inorder, i + 1, iRight); return cur; } }; */ /* 算法思想: 若前序遍历为空或者中序遍历为空则返回空;创建根节点,前序遍历第一个节点是个根节点,在中序遍历中找到根节点相应的位置,可以分别得到左子树和右子树的前序和中序遍历,然后递归重建左右子树;使用辅助空间,存放被分割开的前序和中序遍历的序列。 */ //算法实现: class Solution { public: TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) { //以向量形式给出前序和中序序列 if(preorder.size()==0||inorder.size()==0){ //序列有一个为空,构建的树为空 return NULL; } if(preorder.size()!=inorder.size()){ //序列长度不相同,构建的树为空 return NULL; } vector<int> preorder_l,preorder_r,inorder_l,inorder_r; //辅助空间,存放被分割开的前序和中序遍历的序列 int root_index=-1,len=inorder.size(); TreeNode* root=new TreeNode(preorder[0]); //根节点即前序首节点 for(int i=0;i<len;i++){ // 在中序序列中找出根节点位置 if(preorder[0]==inorder[i]){ root_index=i; //找到根节点在中序序列中的位置 break; } } for(int i=0; i<root_index; i++) { // 左右子树的前序、中序序列 preorder_l.push_back(preorder[i+1]); //这里需要注意, inorder_l.push_back(inorder[i]); } for(int i=root_index+1; i<inorder.size(); i++) { preorder_r.push_back(preorder[i]); inorder_r.push_back(inorder[i]); } root->left=buildTree(preorder_l, inorder_l); //递归重建左子树 root->right = buildTree(preorder_r, inorder_r); //递归重建右子树 return root; } };