《二叉树还原》
首先我们需要知道的是中序遍历,因为这样我们才能知道根的左右子树,否则无法实现还原一棵唯一的二叉树。
已知先序遍历,中序遍历,还原二叉树。
我们知道先序遍历中第一次遇到的一定是根节点。
然后我们就可以根据先序中的根节点位置,在中序遍历中取开辟左右子树。
即递归取分解左右子树。
按照中序的思想,我们会一直去找到左子树的根节点,所以在先序中一开始的一段一般都是左子树的根节点。
具体的做法,就是在一段中先确定根的位置,然后就能左右去分解,然后找出下一次递归的下标和区间即可。
/** * 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: void dfs(vector<int>& preorder, vector<int>& inorder,TreeNode* pre,int id,int pos,int L,int r) { if(L > r) return ; int rt = preorder[pos]; int i = L; TreeNode* node = new TreeNode(rt); if(id == 0) pre->left = node; else pre->right = node; while(inorder[i] != rt) { ++i; } dfs(preorder,inorder,node,0,pos + 1,L,i - 1); dfs(preorder,inorder,node,1,pos + (i - L) + 1,i + 1,r); } TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { TreeNode * rt = new TreeNode(0); int len = preorder.size(); dfs(preorder,inorder,rt,0,0,0,len - 1); return rt->left; } };
已知后序遍历,中序遍历,还原二叉树。
我们可以知道后序遍历一棵子树内的最后一个位置一定是根。
所以我们每次分解子树的时候,都提取它的最后一个作为根,然后去递归分解。
把范围都扣准就行。注意的是为了效率每次我们要去找根在中序中的位置,所以用map来提高速度。
这里发现了一个问题,如果把map也作为形参去传递的话就会超时。
猜测应该是因为map里的东西太多了,每次传递都要做一个拷贝,深度大了之后就超时了。
所以开到全局去用。
class Solution { int post_idx; unordered_map<int, int> mp; public: TreeNode* dfs(vector<int>& inorder, vector<int>& postorder,int le,int ri,int le2,int ri2) { if(le > ri || le2 > ri2) return nullptr; int pos = mp[postorder[ri2]]; TreeNode* node = new TreeNode(postorder[ri2]); node->left = dfs(inorder,postorder,le,pos - 1,le2,le2 + (pos - le - 1)); node->right = dfs(inorder,postorder,pos + 1,ri,le2 + (pos - le),ri2 - 1); return node; } TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { int idx = 0; for (auto& val : inorder) { mp[val] = idx++; } return dfs(inorder,postorder,0, (int)inorder.size() - 1,0, (int)inorder.size() - 1); } };