剑指offer - 重建二叉树 - C++

二刷

重头到尾自己写的,而且比原答案还好,不得不强调:永远不要放弃思考,你可能会做得更好!

拿到题之后先手动在本子上尝试。凭记忆是根据前序确定根节点,在中序中找到根节点的位置从而把左右子树范围确定

演练之后确定用递归

确定递归核心函数的参数时候,秉持不重复的原则,刚开始确定有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貌似使用更广一些,也许还简单一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值