2021.10.6 力扣-从前序与中序遍历序列构造二叉树

题目链接:105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

目录

题目描述:

方法一:

方法二:


题目描述:

方法一:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
 class Solution {
 public:
     TreeNode* build(vector<int>& preorder, vector<int>& inorder, unordered_map<int,int>& inorder_maps, int& preorder_rootindex, int left, int right)
     {
         if (left > right) return nullptr;
         //在前序遍历序列中,找到当前区间中的根节点的val值,并构建根节点
         int root_val = preorder[preorder_rootindex];
         TreeNode* cur = new TreeNode(root_val);
         //前序遍历序列中的下一个数字,即为新的区间中的根节点的val值
         preorder_rootindex++;    
         //中序遍历序列中,根节点的左边即为它的左子树
         int newright = inorder_maps[root_val] - 1;
         cur->left = build(preorder, inorder, inorder_maps, preorder_rootindex, left, newright);
         //中序遍历序列中,根节点的右边即为它的右子树
         int newleft = inorder_maps[root_val] + 1;
         cur->right = build(preorder, inorder, inorder_maps, preorder_rootindex, newleft, right);
         return cur;
     }
     TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
         int n = preorder.size();
         unordered_map<int, int> inorder_maps;  //记录中序遍历序列中,各个元素的位置
         for (int i = 0; i < n; i++)
         {
             inorder_maps[inorder[i]] = i;
         }
         int preorder_rootindex = 0;        //记录当前区间的根节点在前序遍历序列中的位置
         int left = 0;  //当前区间的左指针
         int right = n - 1; //当前区间的右指针
         return build(preorder, inorder, inorder_maps, preorder_rootindex, left, right);
     }
 };

跟【从后序与中序遍历序列构造二叉树】一题一样,今天终于能够自己条理清晰地写出来了。

方法二:

来自2022.8.11的我,发现以前写的太复杂了,变量名取的太长也不是件好事,实在懒得看,自己重新写个简洁点的吧。

大致思路就是先序序列的第一个数就是当前子树的根节点,然后在中序序列中找到这个根节点的下标k,于是在中序序列中位于k左边的就是左子树,位于k右边的就是右子树,于是用递归就可以完成。

class Solution {
public:
    //i1是当前子树的根节点在先序序列中的下标,[i2, j2]是当前子树的所有节点在中序序列中的下标
    TreeNode* build(vector<int>& preorder, vector<int>& inorder, int i1, int i2, int j2)
    {
        if(i2 > j2) return nullptr;
        int key = preorder[i1];
        TreeNode* tmp = new TreeNode(key);
        if (i2 == j2) return tmp;    //当前子树只有一个节点时可以直接返回
        int k;
        //找到当前子树的根节点在中序序列中的下标,以K为边界,左边的就是左子树,右边的就是右子树
        for (k = i2; k <= j2; k++)  
        {
            if (inorder[k] == key) break;
        }
        //i1+1是左子树的根节点在先序序列中的下标,[i2, k-1]是左子树的所有节点在中序序列中的下标
        tmp->left = build(preorder, inorder, i1 + 1, i2, k - 1);
        //k-i2是左子树的节点数量
        //i1+k-i2+1就是右子树的根节点在先序序列中的下标,[k+1, j2]是右子树的所有节点在中序序列中的下标
        tmp->right = build(preorder, inorder, i1 + k - i2 + 1, k + 1, j2);
        return tmp;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        return build(preorder, inorder, 0, 0, n - 1);
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值