重建二叉树(剑指 Offer)

剑指 Offer 07. 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

限制:

0 <= 节点个数 <= 5000

大概思路:

二叉树的前序遍历顺序是:根节点、左子树、右子树,每个子树的遍历顺序同样满足前序遍历顺序。二叉树的中序遍历顺序是:左子树、根节点、右子树,每个子树的遍历顺序同样满足中序遍历顺序。所以根据前序遍历得知前面的就是跟节点,根据这个根节点在中序遍历中就可以确定左子树和右子树。例如:3在preorder的第一个,那么他就是根节点,所以在中序遍历inorder中[9]就是左子树,[15,20,7]就是右子树。层层递归就能得到最终的二叉树

代码实现:

一,

/**
* 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:
	TreeNode* buildTreeCode(vector<int>&preorder, int prestart, int preend, vector<int>& inorder, int inostart, int inoend)
	{
		if (prestart>preend || inostart > inoend)
		{
			return nullptr;
		}
		TreeNode *root = new TreeNode(preorder[prestart]);
		for (auto i = inostart; i <= inoend; i++)
		{
			if (preorder[prestart] == inorder[i])
			{
				root->left = buildTreeCode(
					preorder, prestart + 1, i - inostart + prestart,
					inorder, inostart, i - 1);
				//在前序排列中root就是prestart,所以prestart不在区间内
				root->right = buildTreeCode(
					preorder, i - inostart + prestart + 1, preend,
					inorder, i + 1, inoend);
				//在中序排列中第I个就是root所以在区间内不包括i
				break;
			}
		}
		return root;
	}
	TreeNode* buildTree(vector<int> &preorder, vector<int>&inorder) {
		if (preorder.empty() || inorder.empty())
		{
			return nullptr;
		}
		return  buildTreeCode(
			preorder, 0, preorder.size() - 1,
			inorder, 0, inorder.size() - 1);
	}
};

注意:这个的取值空间的闭的,所以每次都将root节点都不在取值空间内,而且size()-1也是为了取到最后一个元素,保证是一个闭区间。

 

二,收到力扣题解的思路,在其中加入的迭代器。

class Solution {
public:
	TreeNode* buildTreeCode(
		vector<int>::iterator preBegin,
		vector<int>::iterator preEnd,
		vector<int>::iterator inBegin,
		vector<int>::iterator inEnd)
	{
		if (inBegin == inEnd)
		{
			return nullptr;
		}
		TreeNode*cur = new TreeNode(*preBegin);
		auto root = find(inBegin, inEnd, *preBegin);
		cur->left = buildTreeCode(
			preBegin + 1, preBegin + 1 + (root - inBegin),
			inBegin, root);
		//区间是左闭右开
		cur->right = buildTreeCode(
			preBegin + 1 + (root - inBegin), preEnd,
			root + 1, inEnd);
		return cur;
	}

	TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {

		if (preorder.empty() || inorder.empty())
		{
			return nullptr;
		}
		return buildTreeCode(preorder.begin(), preorder.end(),
			inorder.begin(), inorder.end());
	}
};

注:迭代器end是指向性最后这个元素的下一个,所以这个的取值区间是左闭右开的。

这个题的最麻烦的就是确定取值区间,一定要先确定自己的取值区间是什么样的,这样带递归的时候才不会出错

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值