leetcode:Construct Binary Tree from Inorder and Postorder Traversal

Construct Binary Tree from Inorder and Postorder Traversal 

原题目连接地址:https://oj.leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
Runtime:  194 ms

一、实例

后序遍历 DGJHEBIFCA 中序遍历 DBGEHJACIF  请构造二叉树。

二、分析

            1、根据后序遍历的特点,'A' 为树第一层根节点,那么由中序遍历即可得 ‘DBGEHJ’ 和 ‘CIF’ 分别为左右子树;
            2、继续往前扫描后序遍历序列,'C' 为 'A' 右子树根节点,即第二层根节点,‘NULL’ 和 'IF' 分别为 'C' 的左右子树;
            3、继续往前扫描后序遍历序列,'F' 为 'C' 右子树根节点,即第三层根节点,'I' 和 'NULL' 分别为 'F' 的左右子树;
            4、继续往前扫描后序遍历序列,'I' 为 'F' 左子树根节点,即第四层根节点,'NULL' 和 'NULL' 分别为 'I' 的左右子树;
            5、继续往前扫描后序遍历序列,'B' 为 ‘A’ 左子树根节点,即第二层根节点,以此类推得到完整左子树,结果如图。



三、总结

            1、树以递归实现比较清晰易懂简短,但是消耗空间,一般情况下oj平台难以通过。实现思路如下,
                  递归步,以根节点为中心,建立第一层根节点,先构建其右子树,再构建其左子树;再以右子树根节点为中心,递归调用构建右、左子树;直到构建完整树。
                  递归基,如果子树为空,则返回NULL(表示不建立节点);如果子树有一个值,则构建叶节点。
            2、将递归代码转成非递归代码,需要用到栈。实现思路如下,
                  递归步,以根节点为中心,构建第一层根节点,声明定义左子树、右子树,压入栈,同时需要将中序遍历序列中左右子树部分的头尾序号压入栈中;再取出子树,以  其为中心,构建右、左子树,同时将左右子树序号压入栈中;直到构建完整树;
  递归基,如果子树为空,则返回NULL(表示不建立节点);如果子树有一个值,则构建叶节点。
                  此外,还需要加入边界值的判断,如空树、只有根节点的树;其次如果子树为空,需要将已经声明定义好的左右子树delete。
 

四、实现方案


递归实现方案:
<pre name="code" class="cpp">#include<vector>
using namespace std;

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class Solution {
public:
	TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
		if (inorder.size() == 0){
			return NULL;
		}
		if (inorder.size() == 1)
		{
			struct TreeNode *tree = new TreeNode(inorder[0]);
			return tree;
		}
		int i;
		for (i = 0; i < inorder.size(); i++)
		{
			if (inorder[i] == postorder.back())
				break;
		}
		vector<int> postorderCopy = postorder;
		int rootNode = postorderCopy.back();
		postorderCopy.pop_back();
		struct TreeNode *tree = new TreeNode(rootNode);
		vector<int> inorderLeft, inorderRight;
		if (0 <= i - 1)
		{
			//inorderLeft.assign(inorder.begin(), inorder.begin() + i - 1);
			for (int j = 0; j < i; j++)
				inorderLeft.push_back(inorder[j]);
		}
		tree->left = buildTree(inorderLeft, postorderCopy);
		if (i + 1 <= inorder.size() - 1)
		{
			//inorderRight.assign(inorder.begin() + i + 1, inorder.end());
			for (int j = i + 1; j < inorder.size(); j++)
				inorderRight.push_back(inorder[j]);
		}
		tree->right = buildTree(inorderRight, postorderCopy);
		return tree;
	}
};

void preorder_travel(TreeNode *tree)
{
	if (tree == NULL)
	{
		cout << "# ";
		return;
	}
	cout << tree->val <<  " ";
	preorder_travel(tree->left);
	preorder_travel(tree->right);
}

int main(int argc, char **argv[])
{
	vector<int> io = { 2, 3, 1 };
	vector<int> po = { 3, 2, 1 };
	Solution s;
	preorder_travel(s.buildTree(io, po));
	cout << endl;
	return 0;
}


 
  
</pre><pre>
非递归的实现方案:
<pre name="code" class="cpp">class Solution {
public:
	bool deleteNode(TreeNode *root, TreeNode *tree)
	{
		if (root != NULL)
		{
			if (root->right == tree)
			{
				delete tree;
				root->right = NULL;
				return true;
			}
			if (root->left == tree)
			{
				delete tree;
				root->left = NULL;
				return true;
			}
			deleteNode(root->right, tree);
			deleteNode(root->left, tree);
			return false;
		}
	}

	TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
		if (inorder.size() != postorder.size())
			return NULL;
		if (inorder.size() == 0 && postorder.size() == 0)
			return NULL;
		if (inorder.size() == 1 && postorder.size() == 1)
		{
			TreeNode *tree = new TreeNode(inorder[0]);
			return tree;
		}
		vector <int> stack;
		TreeNode *tree = new TreeNode(0);
		vector <TreeNode *> treeStack;
		treeStack.push_back(tree);
		stack.push_back(0);
		stack.push_back(postorder.size() - 1);
		while (treeStack.size() > 0)
		{
			int right = stack.back(); stack.pop_back();
			int left = stack.back(); stack.pop_back();
			TreeNode *tree2 = treeStack.back();
			treeStack.pop_back();
			if (left > right)
			{
				deleteNode(tree, tree2);
				continue;
			}
			if (left == right)
			{
				tree2->val = postorder.back();
				postorder.pop_back();
				continue;
			}
			int i;
			for (i = 0; i < inorder.size(); i++)
			{
				if (inorder[i] == postorder.back())
					break;
			}
			tree2->val = postorder.back();
			postorder.pop_back();
			TreeNode *treeLeft = new TreeNode(0);
			tree2->left = treeLeft;
			treeStack.push_back(treeLeft);
			stack.push_back(left);
			stack.push_back(i - 1);
			TreeNode * treeRight = new TreeNode(0);
			tree2->right = treeRight;
			treeStack.push_back(treeRight);
			stack.push_back(i + 1);
			stack.push_back(right);
		}
		return tree;

	}
};


 
  
 
   
  
 
  
 
 

五、对比提升

          在网上找到一个43ms的方案,用递归实现。其充分利用了后序遍历和中序遍历序列的特点,即两者的左右子树序列是对应的,只要递归的调用构造子树即可完成整棵树的建立,其优点是直接建立节点,如果保存的 start下标 > end下标,则不建立节点。这样子省略了很多变量,值得学习。 如下图:
         原文地址:http://blog.csdn.net/zjull/article/details/11686973 

 
   
  
 
  
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值