Construct Binary Tree from Preorder and Postorder Traversal 根据前序和后序遍历构造二叉树

返回与给定的前序和后序遍历匹配的任何二叉树。

 pre 和 post 遍历中的值是不同的正整数。

示例:

输入:pre = [1,2,4,5,3,6,7], post = [4,5,2,6,7,3,1]
输出:[1,2,3,4,5,6,7]

提示:

  • 1 <= pre.length == post.length <= 30
  • pre[] 和 post[] 都是 1, 2, ..., pre.length 的排列
  • 每个输入保证至少有一个答案。如果有多个答案,可以返回其中一个。

思路:这道题可以从Construct Binary Tree from Inorder and Postorder Traversal 从中序与后序遍历序列构造二叉树Construct Binary Tree from Preorder and Inorder Traversal 从前序与中序遍历序列构造二叉树这两道题中找到解题思路。但是这道题比前两题复杂,因为如果我们根据前序遍历(根左右)和后序遍历(左右根)发现很难区分左子树部分和右子树部分,或者说用前两种方法是无法区分的,所以我们设计一种算法来区分前序遍历和后序遍历的左右子树。其实问题就转化成以下问题,给定字符串pre(代表前序遍历数组)和字符串post(代表后序遍历数组),需要在pre字符串中找到前n个字符,刚好在post的前n个字符中出现。那么我们的核心算法如下:

1:需要hashmap来映射post的值与对应的下标,初始化下标lastIndex=-1和计数器count=0

2:for循环pre的每个字符,如果在hashmap[pre[i]]的值大于lastIndex,意味着当前找到的pre的字符位于post更靠右的地方,那么就更新lastIndex=hashmap[pre[i]]且count+=(hashmap[pre[i]]-lastIndex-post_start) (post_start是post递归的左边界),然后计数器-1,如果这时count==0就意味着已经找到前n个字符使得pre和post的含有相同的前n个字符,直接跳过循环。

这时返回pre对应的左子树的左边界和右边界,即pair<pre_left,i>。

其余部分就是常见的递归,可参考蓝色的两篇帖子。

参考代码:

/**
 * 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:
pair<int, int> divedeLeftAndRight(vector<int>& pre, vector<int>& post, int pre_left, int pre_right, int post_left, int post_right, unordered_map<int, int> &hash) {
	int lastIndex = -1,count=0;
	int i = pre_left;
	for (; i <= pre_right; i++) {
		if (hash[pre[i]] > lastIndex) {
			count += (hash[pre[i]] - lastIndex-post_left);
			lastIndex = hash[pre[i]];
		}
		if(count>0) count--;
		if (count == 0) break;
	}
	return { pre_left,i };
}
TreeNode* constructFromPrePostCore(vector<int>& pre, vector<int>& post, int pre_left, int pre_right, int post_left, int post_right,unordered_map<int, int> &hash) {
	if (pre_left > pre_right || post_left > post_right) return nullptr;
	if (pre_left == pre_right && post_left == post_right) return new TreeNode(pre[pre_left]);
	TreeNode* node = new TreeNode(pre[pre_left]);
	pair<int, int> leftPart = divedeLeftAndRight(pre, post, pre_left+1, pre_right, post_left, post_right-1,hash);
	node->left = constructFromPrePostCore(pre, post, leftPart.first, leftPart.second, post_left, post_left + (leftPart.second - leftPart.first+1) - 1,hash);
	node->right= constructFromPrePostCore(pre, post, leftPart.second+1, pre_right, post_left+ (leftPart.second - leftPart.first+1), post_right-1, hash);
	return node;
}
TreeNode* constructFromPrePost(vector<int>& pre, vector<int>& post) {
	if (pre.empty() || post.empty()) return nullptr;
	unordered_map<int, int> hash;
	for (int i = 0; i < post.size(); i++) hash[post[i]] = i;
	return constructFromPrePostCore(pre, post, 0, pre.size() - 1, 0, post.size() - 1,hash);
}
};

猜你喜欢

转载自blog.csdn.net/qq_26410101/article/details/82721173