zoukankan      html  css  js  c++  java
  • 笔试算法题(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
    ",root->left->value,
    54                                                 root->right->value);
    55                 showTree(root->left);
    56                 showTree(root->right);
    57         } else if(root->left!=NULL) {
    58                 printf("%c
    ",root->left->value);
    59                 showTree(root->left);
    60         } else if(root->right!=NULL) {
    61                 printf("%c
    ",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 }
  • 相关阅读:
    Java单例模式
    svn 清理失败 (clean up 失败) 的解决方法
    linux chrome 安装过程记录
    docker
    linux-cat-grep
    linux-批量结束进程
    linux-压缩与解压缩(gz,zip,tar,jar,war)
    git-服务器地址切换
    linux-tomcat连接数查询
    git-无法add文件的问题
  • 原文地址:https://www.cnblogs.com/leo-chen-2014/p/3751182.html
Copyright © 2011-2022 走看看