要求:重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。二叉树节点的定义如下:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode *m_pLeft;
BinaryTreeNode *m_pRight;
};
测试用例:
- 普通二叉树(完全二叉树;不完全二叉树)
- 特殊二叉树(所有节点都没有右子节点的二叉树;所有节点都没有左子节点的二叉树;只有一个节点的二叉树)
- 特殊输入测试(二叉树的根节点指针为nullptr;输入的前序遍历序列和中序遍历序列不匹配)
本题考点:
- 考查对二叉树的前序遍历和中序遍历的理解程度。只有对二叉树的不同遍历算法有了深刻的理解,应聘者才有可能在遍历序列中划分出左右字数对应的子序列。
- 考查分析复杂问题的能力。我们把构建二叉树的大问题分解成构建左右子树的两个小问题。我们发现小问题和大问题在本质上是一致的,因此可以用递归的方法解决。
源代码:
BinaryTreeNode *ConstructCore(int *startPreorder, int *endPreorder, int *startInorder, int *endInorder)
{
//前序遍历序列的第一个数字是根节点的值
int rootValue = startPreorder[0];
BinaryTreeNode *root = new BinaryTreeNode();
root->m_nValue = rootValue;
root->m_pLeft = root->m_pRight = nullptr;
if (startPreorder == endPreorder)
{
if (startInorder == endInorder && *startPreorder == *startInorder)
return root;
else
throw exception("Invalid input");
}
//在中序遍历中找到根节点的值
int *rootInorder = startInorder;
while (rootInorder <= endInorder && *rootInorder != rootValue)
++rootInorder;
if (rootInorder == endInorder && *rootInorder != rootValue)
throw exception("Invalid input");
int leftLength = rootInorder - startInorder;
int *leftPreorderEnd = startPreorder + leftLength;
if (leftLength > 0)
{
//构建左子树
root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1);
}
if (leftLength < endPreorder - startPreorder)
{
//构建右子树
root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder);
}
return root;
}
参考代码:https://github.com/zhedahht/CodingInterviewChinese2/tree/master/07_ConstructBinaryTree
自己代码:https://github.com/quinta2019/Offer/tree/master/07_Q_ConstructBinaryTree