剑指offer 重建二叉树

这个题比较难理解,建议在草稿纸上自己演示一遍程序的执行过程,执行的样例可以按照这个例子
在这里插入图片描述

思路就会慢慢清晰。
规则:先根遍历:根左右。中根遍历:左根右
题目给的两个数组,先根遍历和中跟遍历,先根遍历的第一个元素就是根节点,在中根遍历中,根节点把中根遍历数组分为两部分,分别是左子树和右子树,那么左右子树又可以根据这个性质,再继续划分。整体思路就是这样。
比较难理解的地方就是,如何求出左右子树在中根遍历数组中的起始位置和终止位置。也就是代码中的recur函数的参数,
node->left = recur(root + 1, left, idx_inor[preorder[root]] - 1);
node->right = recur(root + 1 + idx_inor[preorder[root]] - left,idx_inor[preorder[root]] + 1 , right);
recur函数有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:
    vector<int> preorder, inorder;
    unordered_map<int, int> idx_inor;
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        this->preorder = preorder;
        this->inorder = inorder;
        int len = preorder.size();
        for (int i = 0; i < len; i ++) {
            idx_inor[inorder[i]] = i;//中序遍历用hash表存储,可以根据节点的值得到节点在中序数组中的下标
        }
        return recur(0, 0, len - 1);
    }
    TreeNode* recur(int root, int left, int right) {//三个形参都表示下标,root是根节点在preorder的下标,left和right是左右边界在inorder的下标
        if (left > right) return NULL;
        TreeNode* node = new TreeNode(preorder[root]);
        int i = idx_inor[preorder[root]];//记录根节点在中根数组中的下标
        node->left = recur(root + 1, left, i - 1);//上一根节点在先根数组的下标是root,那么根据规则,左子树的根节点下标就是root + 1,左子树的起点就是中根数组的left,终点就是上一根节点的下标i - 1(左根右)
        node->right = recur(root + 1 + i - left, i + 1 , right);//上一根节点在先根数组的下标是root,那么根据规则(根左右,左根右),右子树的根节点就是root + 左子树的节点数 + 1,就是 root + (左子树的右边界 - 左子树的左边界 + 1) + 1,即 root + (i - 1 - left + 1) + 1 = root + i -left + 1,右子树的左边界在中序数组的下标就是i + 1,右边界就是right。
        return node;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值