题目 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例:
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
解1 递归解法
前序:{根,{左子树},{右子树}}
中序:{{左子树},根,{右子树}}
- 通过一个计数指针nCount,遍历前序链表的值
- 获取中序序列中,前序序列中nCount所指元素的位置index(为了提高效率,这里可以通过遍历一遍中序序列建哈希表,将位置和值对应)
- index左边为左子树遍历,右边为右子树遍历
- 将nCount++,从前序中获取左子树的根,中序中获取左子树的遍历子串,递归处理左子树;左子树处理完毕后,同理递归处理右子树。
class Solution {
public:
int nCount = -1;
unordered_map<int,int> inorder_map;
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
//中序遍历建立哈希映射表,不用多次遍历了
for(int i=0 ; i<inorder.size() ; i++)
{
inorder_map[inorder[i]] = i;
}
return Dfs(preorder,inorder,0,inorder.size()-1);
}
TreeNode* Dfs(vector<int>& preorder, vector<int>& inorder,int begin , int end)
{
//1. 异常处理
//1.1 子串不存在
if(begin > end) return NULL;
//2. 逻辑处理
//前序序列指针+1
nCount++;
//创建结点
TreeNode* pNode = new TreeNode;
pNode->val = preorder[nCount];
pNode->left = NULL;
pNode->right = NULL;
//如果只有一个元素
if(begin == end) return pNode;
//如果有多个元素,在中序中找该节点位置
int index = inorder_map[preorder[nCount]];
//3. 递归处理左子树,中序遍历中左子树子串:begin~index-1;
pNode->left = Dfs(preorder,inorder,begin , index-1);
//4. 递归处理右子树,中序遍历中右子树子串:index+1~end;
pNode->right = Dfs(preorder,inorder,index+1,end);
return pNode;
}
};
解2 迭代法
借助栈实现
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
//异常处理
if(preorder.size() == 0) return NULL;
stack<TreeNode*> S;
//遍历中序序列指针
int pIn(0);
//遍历前序序列指针
int i = 0;
//生成根节点,并入栈,并通过pHead标记树根
TreeNode* pHead = new TreeNode(preorder[0]);
//额外的变量
TreeNode* pNode = NULL;
S.push(pHead);
for(int i=1 ; i<preorder.size() ; i++)
{
//如果栈顶结点(即上一个遍历的结点)不等于pIn结点,说明栈顶结点还有左孩子,将左孩子入栈
if(S.top()->val != inorder[pIn])
{
//生成新节点
pNode = S.top();
pNode->left = new TreeNode(preorder[i]);
//栈顶元素的左孩子入栈
S.push(pNode->left);
}
//若相等,说明左孩子遍历到头
else
{
//开始遍历中序序列,比较pIn所指元素是否和栈顶相等,
//相等则pIn所指元素为其父节点左孩子,出栈
while(!S.empty() && S.top()->val == inorder[pIn])
{
//出栈
pNode = S.top();
S.pop();
pIn++;
}
//不相等则pIn所指元素为其父节点的右孩子,父节点是上一个出栈结点
pNode->right = new TreeNode(preorder[i]);
//将该节点入栈
S.push(pNode->right);
}
}
return pHead;
}
};