牛客网在线编程题——树的高度(2)

题目描述

现在有一棵合法的二叉树,树的节点都是用数字表示,现在给定这棵树上所有的父子关系,求这棵树的高度

输入描述:

输入的第一行表示节点的个数n(1 ≤ n ≤ 1000,节点的编号为0到n-1)组成,
下面是n-1行,每行有两个整数,第一个数表示父节点的编号,第二个数表示子节点的编号

输出描述:

输出树的高度,为一个整数
示例1

输入

5
0 1
0 2
1 3
1 4

输出

3


两种解题思路
1、用输入数据构造二叉树,根据二叉树再求树的高度;

2、根据一个节点只有一个父节点的思路求解(需要考虑非法二叉树的情况)。
第一种思路的解题代码(参考代码:https://blog.csdn.net/qq_40269087/article/details/80443682):
#include<iostream>
#include<malloc.h>
using namespace std;
  
typedef struct BiTreeNode//定义节点结构
{
    int data;
    struct BiTreeNode *lchild,*rchild;
}BiTreeNode,*BiTree;
  
void CreateBiTree(BiTree T, int x, int y)//构造二叉树
{
    BiTree t;
    if(T)
    {
        if(T->data==x){
            if(T->lchild==NULL)
            {
                t=(BiTree)malloc(sizeof(BiTreeNode));
                t->data=y;
                t->lchild=NULL;
                t->rchild=NULL;
                T->lchild=t;
            }else if(T->rchild==NULL)
            {
                t=(BiTree)malloc(sizeof(BiTreeNode));
                t->data=y;
                t->lchild=NULL;
                t->rchild=NULL;
                T->rchild=t;
            }
        }else
        {
            CreateBiTree(T->lchild,x,y);
            CreateBiTree(T->rchild,x,y);
        }
    }
}
int Depth(BiTree T)//求树的深度
{
    if(T==NULL){
        return 0;
    }else{
        int m=Depth(T->lchild);
        int n=Depth(T->rchild);
        if(m>n){
            return m+1;
        }else{
            return n+1;
        }
    }
}
  
int main(){
    int n,a,b;
    cin>>n;
    BiTree root;
    root=(BiTree)malloc(sizeof(BiTreeNode));
    root->data=0;
    root->lchild=NULL;
    root->rchild=NULL;
    for(int i=0;i<n-1;i++){
        cin>>a>>b;
        CreateBiTree(root,a,b);
    }
    cout<<Depth(root)<<endl;
    return 0;
}

值得学习的点:1、构造二叉树的关键点①找到待插入节点的父节点②确定是插入到左子树还是右子树。

       2、构造二叉树和求解二叉树的深度都是采用递归的方法,思想可以借鉴,但是需要注意递归算法的通病:比较耗时。

       3、输入数据时,采用二叉树存储数据。值得思考的问题是在解答问题先,需要先考虑好使用什么数据结构来存储输入数据,这样会促使自己去把具体问题,与数据结构相结合,有助于加快解题。

第二种解题思路的代码(参考代码:https://www.nowcoder.com/discuss/11934?type=1&pos=&page=1 评论中的第12楼):

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    int n,a,b;
    cin>>n;
    int nodeindex[n];
    bool flag[n];//节点有效性标志
    for(int i=0;i<n;i++)//初始化
    {
        nodeindex[i]=-1;
        flag[i]=true;
    }
    for(int i=0;i<n-1;i++)
    {
        cin>>a>>b;
        int count=0;
        for(int j=0;j<n;j++)
        {
            if(nodeindex[j]==a)
            {
                count++;
            }
        }
        if(count<2)//合法二叉树
        {
            if(flag[a]==true)
            {
                nodeindex[b]=a;//数组中的下标为子节点,值为父节点
            }else//但是父节点无效,所以其对应的子节点也无效
            {
                flag[b]=false;
            }
        }else//同一个父节点上的子节点数目大于2,为非法二叉树,将多余子节点置为无效节点
        {
            flag[b]=false;
        }
    }
    int max=0;
    int count=0;
    for(int i=0;i<n;i++)//遍历所有的节点,以该节点出发,求对应的树的高度
    {
        if(flag[i])//筛除掉无效节点
        {
            int cur=i;
            while(cur!=-1)
            {
                cur=nodeindex[cur];
                count++;
            }
            if(count>max)
            {
                max=count;
            }
            count=0;
        }
    }
    cout<<max;
    return 0;
}

值得学习的点:1、所有的节点都只对应了唯一一个父节点,利用这种思路可以避开根据输入数据生成二叉树的步骤;

       2、需要排除非法二叉树的情况,就是一个父节点下有超过2个的子节点,选用合适的标志,排除非法情况。

两种思路的比较:

1、个人更加赞同使用思路1中的方法,因为该方法更加的传统,使用性更广泛,关键是在短的时间里很容易想到;

2、方法二就显得十分的巧妙,思路短时间难以形成,并且需要自己去排除非法二叉树的情况(这也是题目比较坑的地方,很多参考代码都没有将这点考虑进去,最终只能达到50%的通过案例)。






原文地址:https://www.cnblogs.com/lipanDL/p/10009208.html