牛客网在线编程题——树的高度(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%的通过案例)。