从前序/后序遍历与中序遍历构造二叉树

题目

Alt

思路

先知道一个定律:从前序/后序遍历+中序遍历可以确定一棵不存在相同节点的二叉树
我们先复习一下深度优先的三个遍历:

  1. 前序遍历:根节点——左子树——右子树
  2. 中序遍历:左子树——根节点——右子树
  3. 后序遍历:左子树——右子树——根节点
所以当我们知道前序遍历和中序遍历后,大体思路如下:
  1. 前序遍历的第一个为根节点
  2. 接着我们去中序遍历中寻找根节点所在位置,那么根节点前面的就是左子树所有的节点,右边就是右子树所有的节点
  3. 总的来说,前序遍历就是[根节点,左子树,右子树],中序遍历就是[左子树,根节点,右子树]
    代码如下:
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
		return Build(preorder, 0, preorder.size()-1, inorder, 0, inorder.size()-1);
	}
	TreeNode* Build(vector<int>&pre,int left1,int right1,vector<int>& in,int left2,int right2) {
		if (left1 > right1 || left2 > right2)
			return NULL;
		TreeNode* root = new TreeNode(pre[left1]);//前序遍历的第一个节点为根节点
		//然后在中序遍历中确定左子树和右子树的节点个数
		int mid = left2;
		for (int i = left2; i < in.size(); i++) {
			if (in[i] == root->val) {
				mid = i;
				break;
			}
		}
		//构建左子树
		root->left = Build(pre, left1 + 1, left1+mid-left2, in, left2, mid-1);
		root->right = Build(pre, left1 + mid - left2 + 1, right1, in, mid + 1, right2);
		return root;
	}
};
知道后序遍历和中序遍历后的大体思路如下:
  1. 后序遍历最后一个节点为根节点
  2. 在中序遍历中寻找根节点所在位置,根节点前面的节点就为左子树所有节点,根节点后边的节点就为右子树所有节点
  3. 总的来说,后序遍历就是[左子树,右子树,根节点],中序遍历就是[左子树,根节点,右子树]
    代码如下:
class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
		return Build(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
	}
	TreeNode* Build(vector<int>& in, int left1, int right1, vector<int>& post, int left2, int right2) {
		if (left1 > right1 || left2 > right2) 
			return NULL;
		TreeNode* root = new TreeNode(post[right2]);
		int mid = left1;
		for (int i = left1; i <= right1; i++) {
			if (in[i] == root->val) {
				mid = i;
				break;
			}
		}
		root->left = Build(in, left1, mid - 1, post, left2, left2 + mid - left1-1);
		root->right = Build(in, mid + 1, right1, post,left2 + mid - left1, right2 - 1);
		return root;
	}
};

总结

重构二叉树的基本思路就是先构造根节点,再构造左子树,接下来构造右子树,其中构造左子树和右子树是一个子问题,递归处理即可。因此我们只关心如何构造根节点,以及如何递归构造左子树和右子树,再从前序,中序,后序遍历的特点来寻找根节点,左子树和右子树各自的范围

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值