前、中序遍历有何意义?
已知条件:前序,中序遍历,重建二叉树。
给出的前序、中序遍历各自有什么意义呢?
前序遍历:根–>左–>右,不难看出无论何时前序遍历第一个肯定是根节点,因此我们找到了根!
剩下只要找到左孩子和右孩子就行了,把左子树、右子树抽象成只有一个节点:左孩子、右孩子,找到这俩孩子就能重构树了,递归就是一个抽象、抽象、抽/(ㄒoㄒ)/~~象的过程!!!
我们看中序遍历:左–>根–>右,咦,只要知道了根节点在哪,左孩子右孩子就在左右两侧,因此我们就可以通过中序遍历找出左右孩子。
因此,前序遍历的意义就是找根节点、中序遍历就是找左节点和右节点(区间长度)。但是如果左右孩子是棵树的话,那通过中序遍历划分的就是一个区间。不着急~~~知道了这个区间(长度),我们就能返回前序遍历划分左右子树区间,每颗子树又可以看作一棵独立的树,再按原先步骤重复划分即可,这就开始没完没了地递归了,何时才到头?我们定义递归函数TreeNode* dfs(int L,int R,vector<int>& preorder,unordered_map<int,int>& hmap,int in_L,int in_R,vector<int>& inorder)
的意义为在[L,R]这个区间内进行重建树操作,当且仅当L>R时返回空姐点。
小技巧:利用哈希表把中序遍历的所有值和索引作为对存起来(key:值,val: 索引),这样通过前序遍历所得的根节点值就能找到中序遍历中对应根节点的位置(part pos),区间也就划分好,区间长度也就能知道。
代码
各位大神面前我就不班门弄斧了,直接上代码,跟我一样的小白们看不懂的欢迎评论区留言~~~
class Solution {
public:
TreeNode* dfs(int pre_L,int pre_R,vector<int>& preorder,unordered_map<int,int>& hmap,int in_L,int in_R,vector<int>& inorder)
{
if(pre_L-pre_R > 0 || in_L-in_R > 0)
return NULL;
TreeNode* root = new TreeNode(preorder[pre_L]);
int partpos = hmap[preorder[pre_L]];
root->left = dfs(pre_L+1, pre_L + (partpos-in_L),preorder,hmap,in_L,partpos-1,inorder);
root->right = dfs(pre_L + (partpos-in_L)+1,pre_R,preorder,hmap,partpos+1,in_R,inorder);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
//hmap key:中序遍历的值 val:中序遍历的索引
unordered_map<int,int> hmap;
for(int i=0;i<inorder.size();i++)
{
hmap[inorder[i]] = i;
}
return dfs(0,preorder.size()-1,preorder,hmap,0,inorder.size()-1,inorder);
}
};```