笔试算法题(36):寻找一棵二叉树中最远节点的距离 & 根据二叉树的前序和后序遍历重建二叉树
出题:求二叉树中距离最远的两个节点之间的距离,此处的距离定义为节点之间相隔的边数;
分析:
- 最远距离maxDis可能并不经过树的root节点,而树中的每一个节点都可能成为最远距离经过的子树的根节点;所以计算出以每个节点为根节点的子树的最 远距离,最后取他们的最大值就是整棵树的最远距离;
- 如果递归层次过多造成系统栈溢出,则可以使用stack堆栈结构存储递归节点,从而使用循环实现
解题:
1 struct Node { 2 int value; 3 Node *left; 4 Node *right; 5 int leftDis; 6 int rightDis; 7 }; 8 9 void MaxDistance(Node *root, int *MaxDis) { 10 /** 11 * 三个递归停止条件 12 * */ 13 if(root==NULL) 14 return; 15 if(root->left==NULL) 16 root->leftDis=0; 17 if(root->right==NULL) 18 root->rightDis=0; 19 20 /** 21 * 处理当前节点之前,首先处理子节点 22 * */ 23 if(root->left!=NULL) 24 MaxDistance(root->left, MaxDis); 25 if(root->right!=NULL) 26 MaxDistance(root->right, MaxDis); 27 28 /** 29 * 递归仅处理了root->left和root->right为根节点的 30 * 最远距离,所以当前已经知道root->left和root->right 31 * 各自的leftDis和rightDis 32 * */ 33 if(root->left!=NULL) { 34 int tempMax=0; 35 if(root->left->leftDis > root->left->rightDis) 36 tempMax=root->left->leftDis; 37 else 38 tempMax=root->left->rightDis; 39 root->leftDis=tempMax+1; 40 } 41 if(root->right!=NULL) { 42 int tempMax=0; 43 if(root->right->leftDis > root->right->rightDis) 44 tempMax=root->right->leftDis; 45 else 46 tempMax=root->right->rightDis; 47 root->rightDis=tempMax+1; 48 } 49 /** 50 * 更新全局的最远距离MaxDis,最初调用的时候需要赋值为-1 51 * */ 52 if(*MaxDis < root->leftDis + root->rightDis) 53 *MaxDis=root->leftDis + root->rightDis; 54 }
出题:如果已经知道一棵二叉树的前序和中序遍历结果,如何快速重建二叉树。如果知道前序和后序,或者知道中序和后序,是否仍旧可以重建;
分析:
- 下述为一个二叉树的例子,对应的前序,中序和后序遍历如下:
Pre: abdehcfgi
In: dbehafcig
Suffix: dhebfigca
![]() |
- 如果仅知道Pre和In,Pre序列的第一个字符必定为当前子树的根节点(a),所以对应到In序列中,可以根节点为分界(a)将左右子树分开(dbeh 和fcig),然后递归直到仅剩下一个字符;
- Suffic和In也同理,但是仅知道Pre和Suffix不能重建二叉树。
解题:
1 struct Node { 2 int value; 3 Node *left; 4 Node *right; 5 }; 6 7 Node* RestoreTree(char *pre, int pre1, int pre2, 8 char *in, int in1, int in2) { 9 if(pre1>pre2 || in1>in2) return NULL; 10 /** 11 * 当前pre的第一个字符必定是一棵子树的根节点 12 * 所以首先创建一个节点 13 * */ 14 Node *temp=new Node(); 15 temp->value=pre[pre1]; 16 temp->left=NULL; 17 temp->right=NULL; 18 19 /** 20 * 当pre1和pre2相等时,说明已经只有一个字符 21 * 则说明二叉树已经到达子节点,直接返回 22 * */ 23 24 if(pre1==pre2 || in1==in2) 25 return temp; 26 27 /** 28 * 查找pre[pre1]在in序列中的位置 29 * */ 30 int i; 31 for(i=in1;i<=in2;i++) { 32 if(pre[pre1]==in[i]) 33 break; 34 } 35 36 /** 37 * 对pre和in序列进行划分,注意当一个节点仅有左子节点 38 * 或者只有右子节点时,pre1可能大于pre2 39 * */ 40 temp->left=RestoreTree(pre, pre1+1, pre1+(i-in1), 41 in, in1, i-1); 42 temp->right=RestoreTree(pre, pre1+(i-in1)+1, pre2, 43 in, i+1, in2); 44 45 return temp; 46 } 47 48 void showTree(Node *root) { 49 if(root==NULL) 50 return; 51 52 if(root->left!=NULL && root->right!=NULL) { 53 printf("%c, %c\n",root->left->value, 54 root->right->value); 55 showTree(root->left); 56 showTree(root->right); 57 } else if(root->left!=NULL) { 58 printf("%c\n",root->left->value); 59 showTree(root->left); 60 } else if(root->right!=NULL) { 61 printf("%c\n",root->right->value); 62 showTree(root->right); 63 } 64 } 65 66 int main() { 67 char pre[]="abdehcfgi"; 68 char in[]="dbehafcig"; 69 70 Node *root=RestoreTree(pre, 0, 8, in, 0, 8); 71 showTree(root); 72 return 0; 73 }