1. 程式人生 > >阿里14筆試題-求一個二叉樹最大值和最小值的差值絕對值

阿里14筆試題-求一個二叉樹最大值和最小值的差值絕對值

阿里巴巴面試題:

輸入:一個二叉樹

輸出:二叉樹的最大值和最小值的差值絕對值

單純從演算法功能上來看

1-可以先建立一個大根堆,把最大的元素挑出來;

2-然後在建立小根堆,把最小的元素挑出來;

3-在求最大和最小差值的絕對值;

程式碼:

#if 0
/*
最大堆排序
*/
#include<stdio.h>
#include<stdlib.h>
#define LeftChild(i) ( 2*i + 1 )
// 下標 i = 0 儲存是最大的值 , 所以leftchild 是 2×i + 1 ;
void PercDown(int a[] , int i , int n) //最大的下濾
{
    int child , temp ;
    for( temp = a[i] ; LeftChild(i) < n ; i = child )
    {
        child = LeftChild(i);
        if ( (child != n -1) && (a[child+1] > a[child]) ) //選擇最大的孩子節點,
            child++;
        if( temp < a[child] )
            a[i] = a[child] ; //把孩子節點賦值給  父節點
        else
            break;
    }
    a[i] = temp ;
}

void PercUp(int a[] , int i , int n) //最小的上濾
{
    int child , temp ;
    for( temp = a[i] ; LeftChild(i) < n ; i = child )
    {
        child = LeftChild(i);
        if ( (child != n -1) && (a[child+1] < a[child]) ) // 選擇最小的節點 若右孩子小於左孩子,所以要用右孩子去和根節點比較
            child++;
        if( temp > a[child] )
            a[i] = a[child] ;//把最小的孩子  賦值給父節點
        else
            break;
    }
    a[i] = temp ; //把之前節點 賦值給當前需要交換的節點
}

void Swap(int *a , int *b)
{
    int *Tmp ;
    *Tmp = *a ;
    *a = *b ;
    *b = *Tmp ;
}
int HeapSort(int a[] ,int n )
{
    int i , Tmp_Larger ,Tmp_Smaller ;
    for(i = n/2 ; i >= 0 ; i-- ) // n/2 標號最大分支節點,即最大的非葉子節點標號 ;
        PercDown(  a , i , n ); //求最大堆,採用下濾,使最大的浮上來
    #if 0
   printf("The first build large heap:\n");
    for(i = 0 ; i < n ; i++ )
        printf("%d \t" , a[i]);
        printf("\n");
    #endif
    Tmp_Larger = a[0];
    printf("larger : %d \n" ,a[0]);

    #if 0 //this code for heap sort
    for(i = n -1 ; i > 0 ; i-- )
    {
        Swap( &a[0] , &a[i] ) ;  //本程式碼 堆排序是陣列從下標0開始的 ,堆的最後元素和堆的首元素交換 ,僅僅用一個數組就可以排序
        PercDown(a , 0 , i ) ;
    }
    #endif


     for(i = n/2 ; i >= 0 ; i-- ) // n/2 標號最大分支節點,即最大的非葉子節點標號 ;
        PercUp(  a , i , n ); //求最小堆,採用上濾,使最小的浮上來
    #if 0
    printf("The first build smaller heap:\n");
    for(i = 0 ; i < n ; i++ )
        printf("%d \t" , a[i]);
        printf("\n");
    #endif
    Tmp_Smaller = a[0];
    printf("smaller : %d \n" ,a[0]);

    return abs(Tmp_Larger - Tmp_Smaller);
}

int main()
{   int a[] = {31,41,59,26,53,58,97,-1,100}; //測試陣列
    int len , i ;
    len = sizeof(a)/sizeof(int);
    i = HeapSort( a , len );  //建立堆
    printf("This is a HeapSort Data: %d\n",i);


  #if 0
    for(i = 0 ; i < len ; i++ ) //遍歷已經拍好序的陣列
        printf("%d \t" , a[i]);
  #endif
    return 1;
}
#endif
結果:
larger : 100
smaller : -1
This is a HeapSort Data: 101


Process returned 1 (0x1)   execution time : 0.028 s
Press any key to continue.

不過從工程上來說,這樣的程式碼肯定是不行的,需求一改那這個程式碼又需要修改,比如:求最大和中間差值的絕對值。那這個程式碼就不行了,所以先排序然後在按需求輸出,就爽爆天了!

排序:先看排序的數量,數量大優先選用快排,數量小用插入;

程式碼:

#include<stdio.h>
#define cutoff 3
void Swap(int *a ,int *b)
{
    int *temp ;
    *temp = *a;
    *a = *b;
    *b = *temp;
}
int Median3(int a[] ,int Left , int Right)
{
    int Center ;
    Center = (Left + Right )/2 ;

    if (a[Left] > a[Center])
        Swap(&a[Left] , &a[Center]);
    if (a[Left] > a[Right])
        Swap(&a[Left] , &a[Right]);
    if (a[Center] > a[Right])
        Swap(&a[Center] , &a[Right]);
    Swap(&a[Center] , &a[Right-1]);//把樞紐元素和放在倒數第二個位置  ,Left < Center , Right > Center ; 所以開始比較就不用從Left && Righr開始
    return a[ Right-1 ] ;
}

void InsertionSort( int A[ ], int N )
{
    int j, P;
    int  Tmp;

    for( P = 1; P < N; P++ )
    {
        Tmp = A[ P ];
        for( j = P; j > 0 && A[ j - 1 ] > Tmp; j-- )
            A[ j ] = A[ j - 1 ];
        A[ j ] = Tmp;
    }
}
void Qsort(int a[] , int Left , int Right )
{
    int i , j ;
    int Pivot ;
    if ( Left + cutoff <= Right ) //
    {
        Pivot = Median3(a,Left,Right);
        i = Left ; j = Right -1 ;
        for( ; ; )
        {
            while( a[++i] < Pivot ){}
            while( a[--j] > Pivot ){}
            if ( i < j )
                Swap(&a[i] , &a[j]);
            else
                break;
        }
        Swap(&a[i] , &a[Right-1]) ;
        Qsort(a,Left,i-1) ;
        Qsort(a,i+1,Right) ;
    }
    else
    {
             InsertionSort(a+Left , Right - Left + 1) ;
         //    printf("using InsertionSort ! \n");
    }

}
int main()
{
   int i,a[] = {31,41,59,26,53,58,97,-1,100}; //測試陣列
   int len = sizeof(a)/sizeof(int);
   Qsort( a , 0 , len );
   printf("The sort after : \n");
   for( i = 0 ; i < len ; i++ )
        printf("%d \t " ,a[i] );
    printf("\n");
    printf("The vuale of largest and smaller is : %d ", a[len-1] - a[0] );
    return 0;
}
結果:

The sort after :
-1       26      31      41      53      58      59      97      100
The vuale of largest and smaller is : 101
Process returned 0 (0x0)   execution time : 0.023 s
Press any key to continue.