重建二叉树

下面有彩蛋

题目描述

输入一棵二叉树前序遍历和中序遍历的结果,请重建该二叉树。

注意:

  • 二叉树中每个节点的值都互不相同;
  • 输入的前序遍历和中序遍历一定合法;
样例
Input: 
前序遍历:[3,9,20,15,7]
中序遍历:[9,3,15,20,7]
Output: [3,9,20,null,null,15,7,null,null,null,null]
返回的二叉树如下所示:
      3
     / \
    9   20
        / \
       15  7

解题思路

  • 描述
    对于涉及二叉树问题,一般都会使用到递归。

    前序遍历(根左右)和中序遍历(左根右)获取整个二叉树的方法:

    1. 获取前序遍历的第一个元素,也就是根。
    2. 在中序遍历中,该根元素会将中序遍历结果分解为两部分,前半部分为左子树,后半部分为右子树。
    3. 根据上面左右子树的个数,在前序遍历中可以得到相应子树的前序遍历
  • 实现代码:

    /*
    使用到的头文件
    #include <vector>
    #include <map>
    
    结构体
    struct TreeNode {
    	int val;
    	TreeNode* left;
    	TreeNode* right;
    	TreeNode(int val)
    	{
    		this->val = val;
    		this->left = NULL;
    		this->right = NULL;
    	}
    };
    */
    
    map<int, int> hashIndex; //存储中序遍历元素的位置
    vector<int> preorder; //全局变量存储前序和中序遍历,方便使用dfs
    vector<int> inorder; 
    
    //递归实现重建二叉树
    //pl,pr表示前序遍历元素下标范围[pl,pr],il,ir表示中序遍历元素下标范围[il,ir]
    TreeNode* dfs(int pl, int pr, int il, int ir)
    {
    	if (pl > pr) //表示不存在根元素,返回NULL
    	{
    		return NULL;
    	}
    
    	TreeNode* root = new TreeNode(preorder[pl]); //获取根节点
    	int k = hashIndex[preorder[pl]]; //获取该根节点在中序遍历中的位置
    
        //左右子树对应前序遍历和中序遍历下标范围
    	root->left = dfs(pl + 1, pl + k - il, il, k - 1);
    	root->right = dfs(pl + k - il + 1, pr, k + 1, ir);
    
    	return root; //返回该根节点
    }
    
    TreeNode* buildTree(vector<int> &_preorder, vector<int> &_inorder)
    {
    	preorder = _preorder;
    	inorder = _inorder;
    
    	for (int i = 0; i < inorder.size(); i++)
    	{
    		hashIndex[inorder[i]] = i; //使用hashIndex记录中序遍历每一个元素的位置
    	}
    
    	return dfs(0,preorder.size() - 1,0 ,inorder.size());
    }
    

二叉树层序遍历

/*
使用到的头文件
#include <queue>
*/

void print(TreeNode* head) 
{
	TreeNode* tmp;
	queue<TreeNode*> que;
	if (head == NULL)
	{
		return ;
	}
	
	que.push(head);
	while (!que.empty())
	{
		tmp = que.front();
		que.pop();
		if (tmp == NULL)
		{
			cout << "null" << " ";
		}
		else
		{
			cout << tmp->val << " ";
			que.push(tmp->left);
			que.push(tmp->right);
		}
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值