105 从前序与中序遍历序列构造二叉树

24 篇文章 1 订阅

题目

给定一棵树的前序遍历 preorder 与中序遍历 inorder。请构造二叉树并返回其根节点。

示例 1:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

示例 2:
Input: preorder = [-1], inorder = [-1]
Output: [-1]

  • 方法一:递归
/**
 * 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 {
private:
    unordered_map<int, int> index;//储存中序遍历序列中每个节点元素所对应的下标
public:
	//传入六个参数
	//前序遍历序列,中序遍历序列,前序遍历序列的最左节点,前序遍历序列的最有节点,中序遍历序列的最左节点,中序遍历序列的最右节点
    TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder, int preleft, int preright, int inleft, int inright){
    	//递归出口
        if(preleft >preright) return NULL;
        //前序遍历序列的第一个节点就是根节点
        //用根节点查找哈希表找到中序遍历序列中的位置,该节点将中序遍历序列划分为两部分,分别是左子树和右子树
        int preroot = preleft;
        int inroot = index[preorder[preroot]];
        //建立根节点
        TreeNode *root = new TreeNode(preorder[preroot]);
        int left_subtree_size = inroot - inleft;//计算左子树的节点数目
        //递归调用得到左子树和右子树
        root->left = myBuildTree(preorder, inorder, preleft+1,preleft+left_subtree_size,inleft,inroot-1);
        root->right = myBuildTree(preorder, inorder, preleft+left_subtree_size+1, preright, inroot+1,inright);
        return root;
    }

	//建立哈希表储存中序遍历序列中每个节点的值所对应的下标
	//递归调用建树函数建立二叉树
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        for(int i=0; i<n; i++)
            index[inorder[i]] = i;
        return myBuildTree(preorder, inorder, 0, n-1, 0, n-1);
    }
};
  • 时间复杂度O(n)
  • 空间复杂度O(n)
  • 思路
    • 先建立根节点,再递归调用建立其左右子树
    • 前序遍历序列的第一个节点为根节点的元素,根据该元素查找哈希表找到中序遍历序列中的位置,该位置将中序遍历序列划分为两部分,左边的为左子树,右边的为右子树。建立根节点,它的左孩子指向递归调用建立左子树的返回值,它的右孩子指向递归调用建立右子树的返回值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值