二刷
重头到尾自己写的,而且比原答案还好,不得不强调:永远不要放弃思考,你可能会做得更好!
拿到题之后先手动在本子上尝试。凭记忆是根据前序确定根节点,在中序中找到根节点的位置从而把左右子树范围确定
演练之后确定用递归
确定递归核心函数的参数时候,秉持不重复的原则,刚开始确定有5个:
TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin,
int preStart, int vinStart, int length)
但是总觉得有点啰嗦。A出来后,尝试用迭代器,可以少传俩:
TreeNode* reConstructBinaryTree(vector<int>::iterator preStart,
vector<int>::iterator vinStart,
int length)
改成迭代器之后一次过,给自己点个赞,代码:
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) {
int length = pre.size();
vector<int>::iterator preStart = pre.begin();
vector<int>::iterator vinStart = vin.begin();
return reConstructBinaryTree(preStart, vinStart, length);
}
TreeNode* reConstructBinaryTree(vector<int>::iterator preStart,
vector<int>::iterator vinStart,
int length) {
if(length == 0) return nullptr;
int head = *preStart;
TreeNode* pHead = new TreeNode(head);
if(length == 1) return pHead;
int i=0;
for(; i<length; i++) {
if(*(vinStart+i) == head) break;
}
int leftLength = i;
int rightLength = length-1-leftLength;
pHead->left = reConstructBinaryTree(preStart+1, vinStart, leftLength);
pHead->right = reConstructBinaryTree(preStart+1+leftLength, vinStart+1+leftLength,
rightLength);
return pHead;
}
};
而且要夸奖一下自己边界条件写得也十分简练,只在子函数中有
对比之前版本虽然递归子函数是另外写的,但是没有另外创建vector,应该是节省了空间,但是答案的占用空间一样?之后有心情再想想为什么吧
推测一刷是参考了评论区后写出来的
/**
* 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* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
int len = pre.size();
if(len != vin.size()) // throw std::exception("invalid input");
return nullptr;
if(len <= 0) return nullptr;
int rootValue = pre[0];
TreeNode* root = new TreeNode(rootValue);
if(len == 1 && pre[0] == vin[0]) {
return root;
}
// 在中序遍历序列中找到跟节点的值
int inRootIndex = 0;
while(inRootIndex < len && vin[inRootIndex]!=rootValue) {
inRootIndex++;
}
// 没有找到
if(inRootIndex == len) //throw std::exception("invalid input");
return nullptr;
vector<int> leftPre, rightPre, leftVin, rightVin;
for(int i=0; i<inRootIndex; i++) {
leftVin.push_back(vin[i]);
leftPre.push_back(pre[i+1]);
}
for(int i=inRootIndex+1; i<len; i++) {
rightVin.push_back(vin[i]);
rightPre.push_back(pre[i]);
}
root->left = reConstructBinaryTree(leftPre, leftVin);
root->right = reConstructBinaryTree(rightPre, rightVin);
return root;
}
};
太开心啦!除了throw报错不知道怎么写,改成了return nullptr之外,一次过!
对的,今天学了树。
书上的代码是按作者的习惯写出来的,看的话有一些细节自己不能完全吸收,所以,理清思路,找到关键点之后按照自己的方式,更容易一些。
另外,书上的参数是数组的地址指针。数组按地址顺序存放,两地址指针相减可以得出之间的元素数量,所以书上重新写了一个函数用作递归,传参是前序遍历数组的头尾元素地址、中序遍历数组的头尾元素地址,四个参数。我不清楚vector是不是这样存储的。参考讨论区的代码,我的递归是调用题目给的函数,因为参数已经定了所以重新创建的vector,2个参数,但是额外用了一些空间。
顺带一提,我可能又要用java了,因为java貌似使用更广一些,也许还简单一些。