面试题7:重建二叉树
题目:
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树,假设该输入的前序遍历和中序遍历的结果都不含有重复的数字。例如,输入前序遍历序列{1,2,4,7,3,5,6,8}
和中序遍历序列{4,7,2,1,5,3,8,6}
,则重建二叉树并输出他的头结点。二叉树定义如下:
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
思路:
因为前序遍历是:中左右,中序遍历是:左中右。所以想到的是通过前序遍历先去判断每一个分支的中树,然后再根据在中序遍历的中的划分去判断左右子树,比如前序遍历最先的是1所以1就是一个根节点,然后再中序遍历中找到1把中序遍历划分为4,7,2
和5,3,8,6
,前者就为了根节点的左边子树,后着就为根节点的右边子树。
代码:
TreeNode* result(vector<int>& preorder, vector<int>& inorder){
if(inorder.size()==0)
return nullptr;
int index = preorder[0];
TreeNode* head = new TreeNode(index);
preorder.erase(preorder.begin());
auto item = find(inorder.begin(),inorder.end(),index);
vector<int> inorder_left(inorder.begin(),item);
vector<int> inorder_right(item+1,inorder.end());
vector<int>preorder_left(preorder.begin(),preorder.begin()+inorder_left.size());
vector<int>preorder_right(preorder.begin()+inorder_left.size(),preorder.end());
head->left = result(preorder_left,inorder_left);
head->right = result(preorder_right,inorder_right);
return head;
}
考点:
- 考察对前序遍历和中序遍历的理解
- 考察分析复杂问题能力,我们把构建二叉树的大问题分解成为构建左、右子树的两个小问题。
复习三种遍历顺序:
/*--------------------------------递归实现遍历--------------------------------*/
void X_f(TreeNode* head)
{
if (head == nullptr)
return;
cout << head->val << " ";
X_f(head->left);
X_f(head->right);
}
void Z_f(TreeNode* head)
{
if (head == nullptr)
return;
Z_f(head->left);
cout << head->val << " ";
Z_f(head->right);
}
void H_f(TreeNode* head)
{
if (head == nullptr)
return;
H_f(head->left);
H_f(head->right);
cout << head->val << " ";
}
/*--------------------------------迭代实现遍历(非递归)--------------------------------*/
/*
* 先序遍历
* 1)先把头结点压入栈
* 2)从栈中弹出一个节点cur
* 3)打印处理cur
* 4)先右再左压入栈(如果有的话)
* 5)循环
*/
void X_f_1(TreeNode* head)
{
cout << "先序遍历(非递归)" << endl;
if (head != nullptr)
{
stack<TreeNode*>S;
S.push(head);
while (!S.empty())
{
head = S.top();
S.pop();
cout << head->val << " ";
if (head->right != nullptr)
S.push(head->right);
if (head->left != nullptr)
S.push(head->left);
}
}
}
void Z_f_1(TreeNode* head)
{
cout << "中序遍历(非递归)" << endl;
if (head != nullptr)
{
stack<TreeNode*>S;
while (!S.empty() || head != nullptr)
{
if (head != nullptr) {
S.push(head);
head = head->left;
}
else{
head = S.top();
S.pop();
cout << head->val << " ";
head = head->right;
}
}
}
}
void H_f_1(TreeNode* head)
{
cout << "后序遍历(非递归)" << endl;
if (head != nullptr)
{
stack<TreeNode*>S;
stack<TreeNode*>R;
S.push(head);
while (!S.empty())
{
head = S.top();
S.pop();
R.push(head);
if (head->left != nullptr)
S.push(head->left);
if (head->right != nullptr)
S.push(head->right);
}
while (!R.empty())
{
head = R.top();
R.pop();
cout << head->val << " ";
}
}
}