面试题6:重建二叉树
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
题目分析:
给出一棵树的前序遍历和中序遍历序列,可以唯一确定一颗二叉树。如何重建一颗二叉树,思路容易想到,先确定根结点,再确定左右子树,分别递归构建左右子树。
1. 采用递归方式重建
递归重建左右子树。
代码如下:
class Solution {
public:
struct TreeNode *reConstructTree(vector<int> pre, vector<int> in) {
int len = pre.size();
if (len == 0)
return 0;
return ConstructTree(pre, in, 0, 0, len);
}
TreeNode *ConstructTree(vector<int> pre, vector<int> in, int pstart, int istart, int size) {
TreeNode *root = new TreeNode(pre[pstart]);
int i;
/* 注意是i < istart+size, 细心细心 */
for (i = istart; i < istart + size; i ++) {
if (in[i] == pre[pstart])
break;
}
int left_size = i - istart;
/* right_size可能是负值 */
int right_size = size - left_size - 1;
/* 注意起始位置的变化 */
if (left_size > 0)
root->left = ConstructTree(pre, in, pstart + 1, istart, left_size);
/* 注意右子树的起始位置不是i+1? */
if (right_size > 0)
root->right = ConstructTree(pre, in, pstart + left_size + 1, i + 1, right_size);
return root;
}
};
2. 采用辅助栈
能用递归实现的,自然可以用栈转化为非递归实现。
关键是如何判断哪个结点是右子树上的。
思路:
根据前序序列入栈,一直入到当前栈顶结点和中序遍历的结点相等,则走到了最左。
以中序序列为基准,前序序列做为入栈顺序。
代码如下:
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in) {
int len = pre.size();
if (len == 0)
return 0;
stack<TreeNode *> stk;
TreeNode *root = new TreeNode(pre[0]);
TreeNode *cur = root;
stk.push(root);
bool flag = false;
int pt = 1, it = 0;
while (pt < len || it < len) {
if (!stk.empty() && stk.top()->val == in[it]) {
cur = stk.top();
stk.pop();
++ it;
flag = true;
} else {
TreeNode *temp = new TreeNode(pre[pt ++]);
if (flag) {
cur->right = temp;
flag = false;
} else {
stk.top()->left = temp;
}
stk.push(temp);
}
}
return root;
}
};