题目链接
Leetcode 面试题07 重建二叉树
题目要求
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
分析
- 遍历顺序:前序(根-左-右),中序(左-根-右)
- 前序遍历的第一个节点一定是根节点,中序遍历的左右位置代表节点在二叉树中左右相对位置。
- 按前序遍历顺序创建二叉树,节点生成顺序为前序遍历顺序。每次新生成的节点,根据中序遍历确定其位置。
- 当前前序遍历节点下标为pr,下一个节点,即新生成的节点下标为pr+1
使用堆栈保存之前生成的节点,当新生成的节点确定位置并加入二叉树后,将节点压栈。 - 利用中序遍历中pr和pr+1节点值对应位置判断新节点位置,当pr+1节点位置inNext<inCur,说明新节点在当前遍历节点的左边,当前遍历节点左孩子指针指向新节点。
- 当inNext>inCur,说明新节点在当前遍历节点及当前遍历节点到根节点间的某一个节点右边。该位置应该在最后一个满足inNext>inStack处,inStack为之前压栈节点所在中序遍历序列中位置。
- 采用迭代法进行二叉树建立。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size() == 0) return NULL;
TreeNode* root = new TreeNode(preorder[0]);
TreeNode* stack[5001];
TreeNode* nodeNow = NULL;
TreeNode* nodeNext = NULL;
nodeNow = root;
int top = 0;
stack[++top]= nodeNow;
int pr,i;
vector<int>::iterator itInCur,itInNext,itInStack;
for(pr=0;pr<preorder.size()-1; pr++){
nodeNext = new TreeNode(preorder[pr+1]);
itInCur = find(inorder.begin(), inorder.end(), preorder[pr]);
itInNext = find(inorder.begin(), inorder.end(), preorder[pr+1]);
if(itInNext<itInCur){
nodeNow->left = nodeNext;
stack[++top]= nodeNext;
nodeNow = nodeNext;
}
else{
if(top!=0){
i = top;
do{
itInStack = find(inorder.begin(), inorder.end(), stack[i]->val);
if(itInStack<itInNext) i--;
}while(i!=0 && itInStack<itInNext);
top = i + 1;
stack[top]->right = nodeNext;
top--;
stack[++top]= nodeNext;
nodeNow = nodeNext;
}
}
}
return root;
}
};
扩展
只采用前序遍历进行二叉树创建,空节点用“#”表示,则上面的用例表示为[3,9,#,#,20,15,#,#,7,#,#]
创建时采用堆栈进行迭代
代码
Status CreateBiTree(BiTree T, char *String) {//用先序序列建立二叉链表
//String保存输入字符,按先序序列,无空格进行输入,‘#’代表结点为空。根据输入字符进行二叉树创建
BiTree stack[100], Tr, Tq;
int i = 1, top = 0, n = 1;
T->data.num = 0;
T->lchild = T->rchild = NULL;
if (String[0] == '#') {//若树根不存在,返回不执行
return INFEASTABLE;
}
Tr = (BiTree)malloc(sizeof(BiTNode));//为当前指针分配存储空间
Tr->data.value = String[0]; //为当前节点赋值
Tr->data.num = 1; //为当前节点打标记
Tr->lchild = Tr->rchild = NULL;
T->lchild = Tr; //将当前树根结点指针赋给*T的左孩子
stack[top] = Tr;//根节点入栈
while (String[i] != '\n') { //输入字符还未读取完
if (String[i] != '#') {//读入字符不为空‘#’
Tr = (BiTree)malloc(sizeof(BiTNode));
Tr->data.value = String[i];
Tr->data.num = n+1;
Tr->lchild = Tr->rchild = NULL;
while (stack[top]->rchild != NULL ) top--;//退回至子节点未满的结点上
if (top <= -1) return FALSE;
Tq = stack[top];//栈顶元素赋值给Tq
stack[++top] = Tr;//当前元素进栈
if (String[i - 1] != '#') Tq->lchild = Tr;
else {
Tq->rchild = Tr;
}
n++;
}
else {//读入字符为空‘#’
while (stack[top]->rchild != NULL) top--;
Tq = stack[top];
if (String[i - 1] != '#')//若前一字符不为空,则将栈顶元素左孩子赋空
Tq->lchild = NULL;
else {//前一字符为空,将栈顶元素右孩子赋空值,栈顶元素退栈,栈顶指针左移
Tq->rchild = NULL;
top--;
}
}
i++;//下一个字符
}
T->data.num = n; //头结点保存二叉树结点数
return OK;
}