1. 程式人生 > >牛客網在線編程題——樹的高度(2)

牛客網在線編程題——樹的高度(2)

有一個 兩種 turn lse 深度 while vector 構造二叉樹 出發

題目描述

現在有一棵合法的二叉樹,樹的節點都是用數字表示,現在給定這棵樹上所有的父子關系,求這棵樹的高度

輸入描述:

輸入的第一行表示節點的個數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%的通過案例)。






牛客網在線編程題——樹的高度(2)