阿里14筆試題-求一個二叉樹最大值和最小值的差值絕對值
阿新 • • 發佈:2019-02-02
阿里巴巴面試題:
輸入:一個二叉樹
輸出:二叉樹的最大值和最小值的差值絕對值
單純從演算法功能上來看
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.