您的位置:首页 > 编程语言 > C语言/C++

Leetcode 105. Construct Binary Tree from Preorder and Ignorer Traversal(C++版)

2017-03-27 17:06 549 查看
Given preorder and inorder traversal of a tree, construct the binary tree.

思路分析:

一个前序遍历序列和一个中序遍历序列可以唯一确定一颗二叉树。

1、确定树的根节点:设前序遍历序列存储在preorder,中序遍历序列存储在inorder。前序遍历序列的第一个数字preorder[0]就是根结点的值

2、求解树的子树:找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树。若根节点左边或右边为空,则该方向子树为空;若根节点边和右边都为空,则根节点已经为叶子节点。 

3、递归求解树:将左子树和右子树分别看成一棵二叉树,重复1、2、3步,直到所有的节点完成定位。

/**
* 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:
int getRootIndex(vector<int>&preorder,vector<int> &inorder,int len1){
for(int i = 0; i < len1; i++){
if(preorder[0] == inorder[i])//前序遍历的第一个值即根结点的值,在中序序列中找此值即可找到根结点在中序序列中的位置
return i;
}
return -1;
}

TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int len1 = preorder.size();
int len2 = inorder.size();
if(len1 <= 0 || len2 <= 0 || len1 != len2)
return NULL;

int rootValue = preorder[0];//前序遍历第一个数字即根结点的值
TreeNode* root = new TreeNode(rootValue);//根结点

//如果只有一个节点,则返回root
//只有一个根结点时,遍历序列的长度为1,且值相等
if(len1 == 1 && len2 == 1 && preorder[0] == inorder[0])
return root;

//在中序遍历序列中找到根结点的值
int index = getRootIndex(preorder, inorder, len1);

vector<int> left_preorder, left_inorder, right_preorder, right_inorder;
//构造左子树的前序序列和中序序列
for(int i = 0; i < index; i++){
left_preorder.push_back(preorder[i + 1]);
left_inorder.push_back(inorder[i]);
}
//构造左子树的前序序列和中序序列。len1和len2是等长的,所以在同一个循环中即可。
for(int i = index + 1; i < len1; i++){
right_preorder.push_back(preorder[i]);
right_inorder.push_back(inorder[i]);
}

root -> left = buildTree(left_preorder, left_inorder);
root -> right = buildTree(right_preorder, right_inorder);

return root;
}
};



Submission Result: Memory Limit Exceeded 

内存超限制了。是由于上述代码中申请了左子树、右子树的vector。
那么我们不能重新申请内存,就需要在参数中加上一些索引来指明左右子树的前序序列和中序序列的范围。我们可以添加三个参数,第一个参数为子树的前序序列在总的前序序列中的起始索引,第二个参数为子树的中序序列在总的中序序列中的起始索引,第三个参数为子树的结点个数,也就是子树的前序序列/中序序列的长度。
/**
* 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:
int getRootIndex(vector<int>&preorder,vector<int> &inorder,int len1){
for(int i = 0; i < len1; i++){
if(preorder[0] == inorder[i])//前序遍历的第一个值即根结点的值,在中序序列中找此值即可找到根结点在中序序列中的位置
return i;
}
return -1;
}

TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int len1 = preorder.size();
int len2 = inorder.size();
if(len1 <= 0 || len2 <= 0 || len1 != len2)
return NULL;

return preInBuildTree(preorder, inorder, 0, 0, len1);
}

TreeNode *preInBuildTree(vector<int> &preorder, vector<int> &inorder,int preIndex,int inIndex, int size){
if(size <= 0) return NULL;

int rootValue = preorder[preIndex];//前序遍历第一个数字即根结点的值
TreeNode* root = new TreeNode(rootValue);//根结点

//如果只有一个节点,则返回root
//只有一个根结点时,遍历序列的长度为1,且值相等
if(size == 1 && preorder[preIndex] == inorder[inIndex])
return root;

//在中序遍历序列中找到根结点的值
int index;
for(int i = inIndex; i < inIndex + size ; i ++){//从开始索引处开始查找
if(preorder[preIndex] == inorder[i]){
index = i;
break;
}
}
//根据找到的中序遍历中的根结点,继续划分成左右子树
int leftSize = index - inIndex;
int rightSize = size - leftSize - 1;

//新的左子树的前序和中序序列起始索引为preIndex+1和inIndex
//新的右子树的前序和中序序列起始索引为preIndex + 1 + leftSize和index+1
root -> left = preInBuildTree(preorder, inorder, preIndex + 1, inIndex, leftSize);
root -> right = preInBuildTree(preorder, inorder, preIndex + 1 + leftSize, index + 1, rightSize);

return root;
}
};


通过。

感觉自己对这个不是很熟悉,于是又写了C版本的程序,可是。。可是。。runtime error。。不知道为什么会酱紫。。我也没有找出来哪儿错了,哪位大神知道我一下,帮我找找错误呀~~
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize) {
if(preorder == NULL || inorder == NULL || preorderSize != inorderSize)
return NULL;

int rootValue = preorder[0];
struct TreeNode *root = (struct TreeNode*) malloc(sizeof(struct TreeNode));
root -> val = rootValue;
root -> left = NULL;
root -> right = NULL;

//只有一个节点
if(preorderSize == 1){
if(*preorder == *inorder)
return root;
else{
// cerr << "invalid input" << endl;
exit(0);
}
}

//多于一个节点,查找根结点在中序序列中的位置index,根据该位置将树分成左子树和右子树
int index;
for(int i = 0; i < inorderSize; i ++){
if(preorder[0] == inorder[i]){
index = i;
break;
}
}
//index左边为树的左子树的中序序列,右边为树的右子树的中序序列
int size = inorderSize;
int leftInSize = index;
int rightInSize = size - index - 1;

root -> left = buildTree(&preorder[1],leftInSize , inorder, leftInSize );
root -> right = buildTree(&preorder[leftInSize + 1], rightInSize, &inorder[index + 1], rightInSize);

return root;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐