編程題——31~40

三11、連續子數組的最大和node

     輸入一個整數組,數組裏有正數也有負數。數組中一個或連續的多個整數組成一個子數組。ios

求全部子數組的和的最大值。要求時間複雜度爲O(n)。數組

#include <iostream>
#include <stdio.h>

bool g_InvalidInput = false;

int FindGreatestSumOfSubArray( int* pData, int nLength )
{
  if( pData == NULL || ( nLength <= 0 ) )
  {
    g_InvalidInput = true;
    return 0;
  }

  g_InvalidInput = false;
  
  int nCurSum = 0;
  int nGreatestSum = 0x80000000;
  
  for( int i = 0; i < nLength; ++i )
  {
    if( nCurSum <= 0 )
      nCurSum = pData[ i ];
    else
      nCurSum += pData[ i ];

    if( nCurSum > nGreatestSum )
      nGreatestSum = nCurSum;
  }

  return nGreatestSum;
}

void Test( const char* testName, int* pData, int nLength, int expected, bool expectedFlag )
{
  if( testName != NULL )
    printf( "%s begins: \n", testName );

  int result = FindGreatestSumOfSubArray( pData, nLength );
  if( result == expected && expectedFlag == g_InvalidInput )
    printf( "Passed.\n" );
  else
    printf( "Failed.\n" );
}

// 1, -2, 3, 10, -4, 7, 2, -5
void Test1()
{
  int data[] = { 1, -2, 3, 10, -4, 7, 2, -5 };
  Test( "Test1", data, sizeof( data ) / sizeof( int ), 18, false );
}

// 全部數字都是負數
// -2, -8, -1, -5, -9
void Test2()
{
  int data[] = { -2, -8, -1, -5, -9 };
  Test( "Test2", data, sizeof( data ) / sizeof( int ), -1, false );
}

// 全部數字都是正數
// 2, 8, 1, 5, 9
void Test3()
{
  int data[] = { 2, 8, 1, 5, 9 };
  Test( "Test3", data, sizeof( data ) / sizeof( int ), 25, false );
}

// 無效輸入
void Test4()
{
  Test( "Test4", NULL, 0, 0, true );
}

int main()
{
  Test1();
  Test2();
  Test3();
  Test4();

  return 0;
}

三12、從1到n整數中出現的次數

        輸入一個整數n,求從1到n這n個整數的十進制表示中1出現的次數。例如輸入12,從1到12測試

這些整數中包含1的數字有1, 10, 11和12, 1一共出現了5次。this

#include <iostream>
#include <stdio.h>

int NumberOf1( unsigned int n )
{
  int number = 0;
  while( n )
  {
    if( n % 10 == 1 )
      number++;

    n = n / 10;
  }

  return number;
}

int NumberOfBetween1AndN( unsigned int n )
{
  int number = 0;
  
  for( unsigned int i = 1; i <= n; ++i )
    number += NumberOf1( i );

  return number;
}

void Test( const char* testName, int n, int expected )
{
  if( testName != NULL )
    printf( "%s begins: \n", testName );
    
  if( NumberOfBetween1AndN( n ) == expected )
    printf( "Solution passed.\n" );
  else
    printf( "Solution failed.\n" ); 
    
  printf( "\n" );
}

void Test()
{
  Test( "Test1", 1, 1 );
  Test( "Test2", 5, 1 );
  Test( "Test3", 10, 2 );
  Test( "Test4", 55, 16 );
  Test( "Test5", 99, 20 );
  Test( "Test6", 10000, 4001 );
  Test( "Test7", 21345, 18821 );
  Test( "Test8", 0, 0 );
}

int main()
{
  Test();

  return 0;
}

三十3、把數組拍成最小的數

  輸入一個正整數數組,把數組全部數字拼接起來排成一個數,打印能拼接出的全部數字中最小google

的一個。例如輸入數組{ 3, 32, 321 },則打印出這3個數字能排成的最小數字321323.spa

#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <string.h>

const int g_MaxNumberLength = 10;

char* g_StrCombine1 = new char[ g_MaxNumberLength * 2 + 1 ];
char* g_StrCombine2 = new char[ g_MaxNumberLength * 2 + 1 ];

int compare( const void* strNumber1, const void* strNumber2 )
{
  strcpy( g_StrCombine1, *( const char** )strNumber1 );
  strcat( g_StrCombine1, *( const char** )strNumber2 );

  strcpy( g_StrCombine2, *( const char** )strNumber2 );
  strcat( g_StrCombine2, *( const char** )strNumber1 );

  return strcmp( g_StrCombine1, g_StrCombine2 );
}

void PrintMinNumber( int * numbers, int length )
{
  if( numbers == NULL || length <= 0 )
    return;

  char** strNumbers = ( char** )( new int[ length ] );
  for( int i = 0; i < length; ++i )
  {
    strNumbers[ i ] = new char[ g_MaxNumberLength + 1 ];
    sprintf( strNumbers[ i ], "%d", numbers[ i ] );
  }

  qsort( strNumbers, length, sizeof( char* ), compare );

  for( int i = 0; i < length; ++i )
    printf( "%s", strNumbers[ i ] );
  printf( "\n" );

  for( int i = 0; i < length; ++i )
    delete[] strNumbers[ i ];

  delete[] strNumbers;
}

void Test( const char* testName, int* numbers, int length, char* expectedResult )
{
  if( testName != NULL )
    printf( "%s begins:\n", testName );

  if( expectedResult != NULL )
    printf( "Expected result is: \t%s\n", expectedResult );

  printf( "Actual result is: \t" );
  PrintMinNumber( numbers, length );

  printf( "\n" );
}

void Test1()
{
  int numbers[] = { 3, 5, 1, 4, 2 };
  Test( "Test1", numbers, sizeof( numbers ) / sizeof( int ), "12345" );
}

void Test2()
{
  int numbers[] = { 3, 32, 321 };
  Test( "Test2", numbers, sizeof( numbers ) / sizeof( int ), "321323" );
}

void Test3()
{
  int numbers[] = { 3, 323, 32123 };
  Test( "Test3", numbers, sizeof( numbers ) / sizeof( int ), "321233233" );
}

void Test4()
{
  int numbers[] = { 1, 11, 111 };
  Test( "Test4", numbers, sizeof( numbers ) / sizeof( int ), "111111" );
}

// 數組中只有一個數字
void Test5()
{
  int numbers[] = { 321 };
  Test( "Test5", numbers, sizeof( numbers ) / sizeof( int ), "321" );
}

void Test6()
{
  Test( "Test6", NULL, 0, "Don't print anything." );
}

int main()
{
  Test1();
  Test2();
  Test3();
  Test4();
  Test5();
  Test6();

  return 0;
}

三十4、醜數

    咱們把只含包含因子二、3和5的數稱爲醜數(Ugly Number)。求按從小到大的順序的第指針

1500個醜數。例如六、8都是醜數,但14不是,由於它包含因子7.習慣上咱們把1當作醜數。code

#include <iostream>
#include <stdio.h>

bool IsUgly( int number )
{
  while( number % 2 == 0 )
    number /= 2;
  while( number % 3 == 0 )
    number /= 3;
  while( number % 5 == 0 )
    number /= 5;

  return  ( number == 1 ) ? true : false;
}

int GetUglyNumber_Solution1( int index )
{
  if( index <= 0 )
    return 0;

  int number = 0;
  int uglyFound = 0;
  while( uglyFound < index )
  {
    ++number;
  
    if( IsUgly( number ) )
    {
      ++uglyFound;
    }
  }

  return number;
}

void Test( int index, int expected )
{
  if( GetUglyNumber_Solution1( index ) == expected )
    printf( "solution1 passed\n" );
  else
    printf( "solution1 failed\n" );
}

int main()
{
  Test( 1500, 859963392 );

  return 0;
}

#include <iostream>
#include <stdio.h>

int Min( int number1, int number2, int number3 )
{
  int min = ( number1 < number2 ) ? number1 : number2;
  min = ( min < number3 ) ? min : number3;
 
  return min;
}

// 獲取第k個醜數,假定1爲第一個醜數
int GetUglyNumber_Solution2( int index )
{
  if( index <= 0 )
    return 0;
 
  // 定義醜數數組,用於記錄排序的醜數
  int *pUglyNumbers = new int[ index ];
  // 第一個醜數爲1
  pUglyNumbers[ 0 ] = 1;
  // 第一個醜數的座標是0,下一個醜數的座標從1開始
  int nextUglyIndex = 1;
 
  // 定義三個指向醜數數組的指針,用它們來標識從數組中的哪個數開始計算M2,M3和M5,開始都是醜數數組的首地址
  int *pMultiply2 = pUglyNumbers;
  int *pMultiply3 = pUglyNumbers;
  int *pMultiply5 = pUglyNumbers;
 
  while( nextUglyIndex < index )
  {
    // M2=*T2 * 2, M3=*T3 * 3, M5=*T5 * 5
    int min = Min( *pMultiply2 * 2, *pMultiply3 * 3, *pMultiply5 * 5 );
    // 求M2,M3,M5的最小值做爲新的醜數放入醜數數組
    pUglyNumbers[ nextUglyIndex ] = min;
 
    // 每次生成新的醜數的時候,去更新T2,T3和T5.
    while( *pMultiply2 * 2 <= pUglyNumbers[ nextUglyIndex ] )
      ++pMultiply2;
    while( *pMultiply3 * 3 <= pUglyNumbers[ nextUglyIndex ] )
      ++pMultiply3;
    while( *pMultiply5 * 5 <= pUglyNumbers[ nextUglyIndex ] )
      ++pMultiply5;
 
    ++nextUglyIndex;
  }
 
  // 由於醜數有序排列,因此醜數數組中的最後一個醜數就是咱們所求的第index個醜數。
  int ugly = pUglyNumbers[ nextUglyIndex - 1 ];
  delete[] pUglyNumbers;
  return ugly;
}

void Test( int index, int expected )
{
  if( GetUglyNumber_Solution2( index ) == expected )
    printf( "solution2 passed\n" );
  else
    printf( "solution2 failed\n" );
}

int main()
{
  Test( 1500, 859963392 );

  return 0;
}

三十5、第一個只出現一次的字符

    在字符串中找出第一個只出現一次的字符。如輸入"abaccdeff",則輸出'b'。排序

#include <iostream>
#include <stdio.h>
#include <string>

char FirstNotRepeatingChar( char* pString )
{
  if( pString == NULL )
    return '\0';
  
  const int tableSize = 256;
  unsigned int hashTable[ tableSize ];

  for( unsigned int i = 1; i < tableSize; ++i )
    hashTable[ i ] = 0;

  char* pHashKey = pString;
  while( *( pHashKey ) != '\0' )
    hashTable[ *( pHashKey++ ) ]++;

  pHashKey = pString;
  while( *pHashKey != '\0' )
  {
    if( hashTable[ *pHashKey ] == 1 )
      return *pHashKey;

    pHashKey++;
  }

  return '\0';
}

void Test( char* pString, char expected )
{
  if( FirstNotRepeatingChar( pString ) == expected )
    printf( "Test passed.\n" );
  else
    printf( "Test failed.\n" );
}

int main()
{
  // 常規輸入測試,存在只出現一次的字符
  Test( "google", 'l' );

  // 常規輸入測試,不存在只出現一次的字符
  Test( "aabccdbd", '\0' );

  // 常規輸入測試,全部字符都只出現一次
  Test( "abcdefg", 'a' );

  // 魯棒性測試,輸入NULL
  Test( NULL, '\0' );

  return 0;
}

三十6、數組中的逆序對

     在數組中的兩個數字若是前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸

入一個數組,求出這個數組中的逆序對的總數。

#include <iostream>
#include <stdio.h>

int InversePairsCore( int* data, int* copy, int start, int end )
{
  if( start == end )
  {
    copy[ start ] = data[ start ];
    return 0;
  }

  int length = ( end -start ) / 2;
  
  int left = InversePairsCore( copy, data, start, start + length );
  int right = InversePairsCore( copy, data, start + length + 1, end );

  // i初始化爲前半段最後一個數字的下標
  int i = start + length; 
  // j初始化爲後半段最後一個數字的下標
  int j = end; 
  int indexCopy = end;
  int count = 0;
  while( i >= start && j >= start + length + 1 )
  { 
    if( data[ i ] > data[ j ] )
    {
      copy[ indexCopy-- ] = data[ i-- ];
      count += j - start - length;
    }
    else
    {
      copy[ indexCopy-- ] = data[ j-- ];
    }
  }

  for( ; i >= start; --i )
    copy[ indexCopy-- ] = data[ i ];

  for( ; j >= start + length + 1; --j )
    copy[ indexCopy-- ] = data[ j ];

  return left + right + count;
}

int InversePairs( int* data, int length )
{
  if( data == NULL || length < 0 )
    return 0;

  int* copy = new int[ length ];

  for( int i = 0; i < length; ++i )
    copy[ i ] = data[ i ];

  int count = InversePairsCore( data, copy, 0, length - 1 );
  delete[] copy;
  
  return count;
}

void Test( const char* testName, int* data, int length, int expected )
{
  if( testName != NULL )
    printf( "%s begins: ", testName );

  if( InversePairs( data, length ) == expected )
    printf( "Passed.\n" );
  else
    printf( "Failed.\n" );
}

void Test1()
{
  int data[] = { 1, 2, 3, 4, 7, 6, 5 };
  int expected = 3;

  Test( "Test1", data, sizeof( data ) / sizeof( int ), expected );
}

// 遞減排序數組
void Test2()
{
  int data[] = { 6, 5, 4, 3, 2, 1 };
  int expected = 15;

  Test( "Test2", data, sizeof( data ) / sizeof( int ), expected );
}

// 遞增排序數組
void Test3()
{
  int data[] = { 1, 2, 3, 4, 5, 6 };
  int expected = 0;

  Test( "Test3", data, sizeof( data ) / sizeof( int ), expected );
}

// 數組中只有一個數字
void Test4()
{
  int data[] = { 1 };
  int expected = 0;

  Test( "Test4", data, sizeof( data ) / sizeof( int ), expected );
}

int main()
{
  Test1();
  Test2();
  Test3();
  Test4();
  
  return 0;
}

三十7、兩個鏈表的第一個公共結點

     輸入兩個鏈表,找出它們的第一個公共結點。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

struct ListNode
{
  int m_nValue;
  ListNode* m_pNext;
};

ListNode* CreateListNode( int value )
{
  ListNode* pNode = new ListNode();
  pNode->m_nValue = value;
  pNode->m_pNext = NULL;

  return pNode;
}

void ConnectListNodes( ListNode* pCurrent, ListNode* pNext )
{
  if( pCurrent == NULL )
  {
    printf( "Error to connect two nodes.\n" );
    exit( 1 );
  }

  pCurrent->m_pNext = pNext;
}

void PrintListNode( ListNode* pNode )
{
  if( pNode == NULL )
  {
    printf( "The node is NULL\n" );
  }
  else
  {
    printf( "The key in node is %d.\n", pNode->m_nValue );
  }
}

void PrintList( ListNode* pHead )
{
  printf( "PrintList start: \n" );
  ListNode* pNode = pHead;
  
  while( pNode != NULL )
  {
    printf( "%d\t", pNode->m_nValue );
    pNode = pNode->m_pNext;
  }
}

void DestroyNode( ListNode* pNode )
{
  if( pNode != NULL )
  {
    delete pNode;
  }
}


void DestroyList( ListNode* pHead )
{
  ListNode* pNode = pHead;
  
  while( pNode != NULL )
  {
    pHead = pHead->m_pNext;
    delete pNode;
    pNode = pHead;
  }
}

unsigned int GetListLength( ListNode* pHead )
{
  unsigned int nLength = 0;
  ListNode* pNode = pHead;
  while( pNode != NULL )
  {
    ++ nLength;
    pNode = pNode->m_pNext;
  }
 
  return nLength;
}

ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2 )
{
  // 獲得兩個鏈表的長度
  unsigned int nLength1 = GetListLength(pHead1);
  unsigned int nLength2 = GetListLength(pHead2);
  int nLengthDif = nLength1 - nLength2;
 
  ListNode* pListHeadLong = pHead1;
  ListNode* pListHeadShort = pHead2;
  if( nLength2 > nLength1 )
  {
    pListHeadLong = pHead2;
    pListHeadShort = pHead1;
    nLengthDif = nLength2 - nLength1;
  }
 
  // 先在長鏈表上走幾步,再同時在兩個鏈表上遍歷
  for( int i = 0; i < nLengthDif; ++i )
    pListHeadLong = pListHeadLong->m_pNext;
 
  while( ( pListHeadLong != NULL ) && 
         ( pListHeadShort != NULL ) &&
         ( pListHeadLong != pListHeadShort ) )
  {
    pListHeadLong = pListHeadLong->m_pNext;
    pListHeadShort = pListHeadShort->m_pNext;
  }
 
  // 獲得第一個公共結點
  ListNode* pFisrtCommonNode = pListHeadLong;
 
  return pFisrtCommonNode;
}


void Test( const char* testName, ListNode* pHead1, ListNode* pHead2, ListNode* pExpected )
{
  if( testName != NULL )
    printf( "%s begins: ", testName );

  ListNode* pResult = FindFirstCommonNode( pHead1, pHead2 );
  if( pResult == pExpected )
    printf( "Passed.\n" );
  else
    printf( "Failed.\n" );
}

// 第一個公共結點在鏈表中間
// 1 - 2 - 3 \
//            6 - 7
//     4 - 5 /
void Test1()
{
  ListNode* pNode1 = CreateListNode( 1 );
  ListNode* pNode2 = CreateListNode( 2 );
  ListNode* pNode3 = CreateListNode( 3 );
  ListNode* pNode4 = CreateListNode( 4 );
  ListNode* pNode5 = CreateListNode( 5 );
  ListNode* pNode6 = CreateListNode( 6 );
  ListNode* pNode7 = CreateListNode( 7 );

  ConnectListNodes( pNode1, pNode2 );
  ConnectListNodes( pNode2, pNode3 );
  ConnectListNodes( pNode3, pNode6 );
  ConnectListNodes( pNode4, pNode5 );
  ConnectListNodes( pNode5, pNode6 );
  ConnectListNodes( pNode6, pNode7 );

  Test( "Test1", pNode1, pNode4, pNode6 );

  DestroyNode( pNode1 );
  DestroyNode( pNode2 );
  DestroyNode( pNode3 );
  DestroyNode( pNode4 );
  DestroyNode( pNode5 );
  DestroyNode( pNode6 );
  DestroyNode( pNode7 );
}

// 公共結點是第一個結點
// 1 - 2 - 3 - 4 - 5
// 兩個鏈表徹底重合   
void Test2()
{
  ListNode* pNode1 = CreateListNode( 1 );
  ListNode* pNode2 = CreateListNode( 2 );
  ListNode* pNode3 = CreateListNode( 3 );
  ListNode* pNode4 = CreateListNode( 4 );
  ListNode* pNode5 = CreateListNode( 5 );

  ConnectListNodes( pNode1, pNode2 );
  ConnectListNodes( pNode2, pNode3 );
  ConnectListNodes( pNode3, pNode4 );
  ConnectListNodes( pNode4, pNode5 );

  Test( "Test2", pNode1, pNode1, pNode1 );

  DestroyList( pNode1 );
}

int main()
{
  Test1();
  Test2();
  
  return 0;
}

三十8、數字在排序數組中出現的次數

    統計一個數字在排序數組中出現的次數。例如輸入排序數組{1, 2, 3, 3, 3, 3, 3, 4, 5}和數字3,

因爲3在這個數組中出現了4次,所以輸出4.

#include <iostream>
#include <stdio.h>

int GetFirstK( int* data, int length, int k, int start, int end )
{
  if( start > end )
    return -1;

  int middleIndex = ( start + end ) / 2;
  int middleData = data[ middleIndex ];
  
  if( middleData == k )
  {
    if( ( middleIndex > 0 && data[ middleIndex - 1 ] != k ) || middleIndex == 0 )
      return middleIndex;
    else
      end = middleIndex - 1;
  }
  else if( middleData > k )
    end = middleIndex - 1;
  else
    start = middleIndex + 1;

  return GetFirstK( data, length, k, start, end );
}

int GetLastK( int* data, int length, int k, int start, int end )
{
  if( start > end )
    return -1;

  int middleIndex = ( start + end ) / 2;
  int middleData = data[ middleIndex ];
  
  if( middleData == k )
  {
    if( ( middleIndex < length - 1 && data[ middleIndex + 1 ] != k ) || middleIndex == length - 1 )
      return middleIndex;
    else
      start = middleIndex + 1;
  }
  else if( middleData < k )
    start = middleIndex + 1;
  else
    end = middleIndex - 1;

  return GetLastK( data, length, k, start, end );
}

int GetNumberOfK( int* data, int length, int k )
{
  int number = 0;
  
  if( data != NULL && length > 0 )
  {
    int first = GetFirstK( data, length, k, 0, length - 1 );
    int last = GetLastK( data, length, k, 0, length - 1 );  

    if( first > -1 && last > -1 )
      number = last - first + 1;
  }

  return number;
}

void Test( const char* testName, int data[], int length, int k, int expected )
{
  if( testName != NULL )
    printf( "%s begins: ", testName );

  int result = GetNumberOfK( data, length, k );
  if( result == expected )
    printf( "Passed.\n" );
  else
    printf( "Failed.\n" );
}

// 查找的數字出如今數組的中間
void Test1()
{
  int data[] = { 1, 2, 3, 3, 3, 3, 4, 5 };
  Test( "Test1", data, sizeof( data ) / sizeof( int ), 3, 4 );
}

// 查找的數組出如今數組的開頭
void Test2()
{
  int data[] = { 3, 3, 3, 3, 4, 5 };
  Test( "Test2", data, sizeof( data ) / sizeof( int ), 3, 4 );
}

// 查找的數組出如今數組的結尾
void Test3()
{
  int data[] = { 1, 2, 3, 3, 3, 3 };
  Test( "Test3", data, sizeof( data ) / sizeof( int ), 3, 4 );
}

// 查找的數字不存在
void Test4()
{
  int data[] = { 1, 3, 3, 3, 3, 4, 5 };
  Test( "Test4", data, sizeof( data ) / sizeof( int ), 2, 0 );
}

// 查找的數字比第一個數字還小,不存在
void Test5()
{
  int data[] = {1, 3, 3, 3, 3, 4, 5 };
  Test( "Test5", data, sizeof( data ) / sizeof( int ), 0, 0 );
}

// 查找的數字比最後一個數字還大,不存在
void Test6()
{
  int data[] = { 1, 3, 3, 3, 3, 4, 5 };
  Test( "Test6", data, sizeof( data ) / sizeof( int ), 6, 0 );
}

// 數組中的數字從頭至尾都是查找的數字
void Test7()
{
  int data[] = { 3, 3, 3, 3 };
  Test( "Test7", data, sizeof( data ) / sizeof( int ), 3, 4 );
}

// 數組中的數字從頭至尾只有一個重複的數字,不是查找的數字
void Test8()
{
  int data[] = { 3, 3, 3, 3 };
  Test( "Test8", data, sizeof( data ) / sizeof( int ), 4, 0 );
}

// 數組中只有一個數字,是查找的數字
void Test9()
{
  int data[] = { 3 };
  Test( "Test9", data, sizeof( data ) / sizeof( int ), 3, 1 );
}

// 數組中只有一個數字,不是查找的數字
void Test10()
{
  int data[] = { 3 };
  Test( "Test10", data, sizeof( data ) / sizeof( int ), 4, 0 );
}

// 魯棒性測試,數組空指針
void Test11()
{
  Test( "Test11", NULL, 0, 0, 0 );
}

int main()
{
  Test1();
  Test2();
  Test3();
  Test4();
  Test5();
  Test6();
  Test7();
  Test8();
  Test9();
  Test10();
  Test11();

  return 0;
}

三十9、二叉樹的深度

      輸入一顆二叉樹的根結點,求該樹的深度。從根結點到葉結點依次通過的結點(含根、葉結

點)造成樹的一條路徑,最長路徑的長度爲樹的深度。

#include <iostream>
#include <stdio.h>

struct BinaryTreeNode
{
  int m_nValue;
  BinaryTreeNode* m_pLeft;
  BinaryTreeNode* m_pRight;
};

BinaryTreeNode* CreateBinaryTreeNode( int value )
{
  BinaryTreeNode* pNode = new BinaryTreeNode();
  pNode->m_nValue = value;
  pNode->m_pLeft = NULL;
  pNode->m_pRight = NULL;

  return pNode;
}

void ConnectTreeNodes( BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight )
{
  if( pParent != NULL )
  {
    pParent->m_pLeft = pLeft;
    pParent->m_pRight = pRight;
  }
}

void PrintTreeNode( BinaryTreeNode* pNode )
{
  if( pNode != NULL )
  {
    printf( "value of this node is: %d\n", pNode->m_nValue );

    if( pNode->m_pLeft != NULL )
      printf( "value of its left child is: %d.\n", pNode->m_pLeft->m_nValue );
    else
      printf( "left child is null.\n" );

    if( pNode->m_pRight != NULL )
      printf( "value of its right child is: %d.\n", pNode->m_pRight->m_nValue );
    else
      printf( "right child is null.\n" );
  }
  else
  {
    printf( "this node is null.\n" );
  }

  printf( "\n" );
}

void PrintTree( BinaryTreeNode* pRoot )
{
  PrintTreeNode( pRoot );

  if( pRoot != NULL )
  {
    if( pRoot->m_pLeft != NULL )
      PrintTree( pRoot->m_pLeft );

    if( pRoot->m_pRight != NULL )
      PrintTree( pRoot->m_pRight );
  }
}

void DestroyTree( BinaryTreeNode* pRoot )
{
  if( pRoot != NULL )
  {
    BinaryTreeNode* pLeft = pRoot->m_pLeft;
    BinaryTreeNode* pRight = pRoot->m_pRight;   

    delete pRoot;
    pRoot = NULL;
  
    DestroyTree( pLeft );
    DestroyTree( pRight );
  }
}

int TreeDepth( BinaryTreeNode* pRoot )
{
  if( pRoot == NULL )
    return 0;

  int nLeft = TreeDepth( pRoot->m_pLeft );
  int nRight = TreeDepth( pRoot->m_pRight );

  return ( nLeft > nRight ) ? ( nLeft + 1 ) : ( nRight + 1 );
}

void Test( BinaryTreeNode* pRoot, int expected )
{
  int result = TreeDepth( pRoot );
  if( expected == result )
    printf( "Test passed.\n" );
  else
    printf( "Test failed.\n" );
}

//            1
//         /      \
//        2        3
//       /\         \
//      4  5         6
//        /
//       7
void Test1()
{
  printf( "Test1 begins.\n" );

  BinaryTreeNode* pNode1 = CreateBinaryTreeNode( 1 );
  BinaryTreeNode* pNode2 = CreateBinaryTreeNode( 2 );
  BinaryTreeNode* pNode3 = CreateBinaryTreeNode( 3 );
  BinaryTreeNode* pNode4 = CreateBinaryTreeNode( 4 );
  BinaryTreeNode* pNode5 = CreateBinaryTreeNode( 5 );
  BinaryTreeNode* pNode6 = CreateBinaryTreeNode( 6 );
  BinaryTreeNode* pNode7 = CreateBinaryTreeNode( 7 );

  ConnectTreeNodes( pNode1, pNode2, pNode3 );
  ConnectTreeNodes( pNode2, pNode4, pNode5 );
  ConnectTreeNodes( pNode3, NULL, pNode6 );
  ConnectTreeNodes( pNode5, pNode7, NULL );

  Test( pNode1, 4 );

  DestroyTree( pNode1 );
}

//               1
//              /
//             2
//            /
//           3
//          /
//         4
//        /
//       5
void Test2()
{
  printf( "Test2 begins.\n" );

  BinaryTreeNode* pNode1 = CreateBinaryTreeNode( 1 );
  BinaryTreeNode* pNode2 = CreateBinaryTreeNode( 2 );
  BinaryTreeNode* pNode3 = CreateBinaryTreeNode( 3 );
  BinaryTreeNode* pNode4 = CreateBinaryTreeNode( 4 );
  BinaryTreeNode* pNode5 = CreateBinaryTreeNode( 5 );

  ConnectTreeNodes( pNode1, pNode2, NULL );
  ConnectTreeNodes( pNode2, pNode3, NULL );
  ConnectTreeNodes( pNode3, pNode4, NULL );
  ConnectTreeNodes( pNode4, pNode5, NULL );

  Test( pNode1, 5 );

  DestroyTree( pNode1 );
}

// 樹中只有1個結點
void Test3()
{
  printf( "Test3 begins.\n" );

  BinaryTreeNode* pNode1 = CreateBinaryTreeNode( 1 );
  Test( pNode1, 1 );

  DestroyTree( pNode1 );
}

// 樹中沒有結點
void Test4()
{
  printf( "Test4 begins.\n" );

  Test( NULL, 0 );
}

int main()
{
  Test1();
  Test2();
  Test3();
  Test4();

  return 0;
}

      輸入一顆二叉樹的根結點,判斷該樹是否是平衡二叉樹。若是某二叉樹中任意結點的左右子

樹的深度相差不超過1,那麼它就是一顆平衡二叉樹。

#include <iostream>
#include <stdio.h>

struct BinaryTreeNode
{
  int m_nValue;
  BinaryTreeNode* m_pLeft;
  BinaryTreeNode* m_pRight;
};

BinaryTreeNode* CreateBinaryTreeNode( int value )
{
  BinaryTreeNode* pNode = new BinaryTreeNode();
  pNode->m_nValue = value;
  pNode->m_pLeft = NULL;
  pNode->m_pRight = NULL;

  return pNode;
}

void ConnectTreeNodes( BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight )
{
  if( pParent != NULL )
  {
    pParent->m_pLeft = pLeft;
    pParent->m_pRight = pRight;
  }
}

void PrintTreeNode( BinaryTreeNode* pNode )
{
  if( pNode != NULL )
  {
    printf( "value of this node is: %d\n", pNode->m_nValue );

    if( pNode->m_pLeft != NULL )
      printf( "value of its left child is: %d.\n", pNode->m_pLeft->m_nValue );
    else
      printf( "left child is null.\n" );

    if( pNode->m_pRight != NULL )
      printf( "value of its right child is: %d.\n", pNode->m_pRight->m_nValue );
    else
      printf( "right child is null.\n" );
  }
  else
  {
    printf( "this node is null.\n" );
  }

  printf( "\n" );
}

void PrintTree( BinaryTreeNode* pRoot )
{
  PrintTreeNode( pRoot );

  if( pRoot != NULL )
  {
    if( pRoot->m_pLeft != NULL )
      PrintTree( pRoot->m_pLeft );

    if( pRoot->m_pRight != NULL )
      PrintTree( pRoot->m_pRight );
  }
}

void DestroyTree( BinaryTreeNode* pRoot )
{
  if( pRoot != NULL )
  {
    BinaryTreeNode* pLeft = pRoot->m_pLeft;
    BinaryTreeNode* pRight = pRoot->m_pRight;   

    delete pRoot;
    pRoot = NULL;
  
    DestroyTree( pLeft );
    DestroyTree( pRight );
  }
}

int TreeDepth( BinaryTreeNode* pRoot )
{
  if( pRoot == NULL )
    return 0;

  int nLeft = TreeDepth( pRoot->m_pLeft );
  int nRight = TreeDepth( pRoot->m_pRight );

  return ( nLeft > nRight ) ? ( nLeft + 1 ) : ( nRight + 1 );
}

bool IsBalanced_Solution( BinaryTreeNode* pRoot )
{
  if( pRoot == NULL )
    return true;

  int left = TreeDepth( pRoot->m_pLeft );
  int right = TreeDepth( pRoot->m_pRight );
  int diff = left - right;
  if( diff > 1 || diff < -1 )
    return false;

  return IsBalanced_Solution( pRoot->m_pLeft ) 
         && IsBalanced_Solution( pRoot->m_pRight );
}

void Test( const char* testName, BinaryTreeNode* pRoot, bool expected )
{
  if( testName != NULL )
    printf( "%s begins:\n", testName );

  printf( "Solution begins: " );
    if( IsBalanced_Solution( pRoot ) == expected )
      printf( "Passed.\n" );
    else
      printf( "Failed.\n" );
}

// 徹底二叉樹
//             1
//         /      \
//        2        3
//       /\       / \
//      4  5     6   7
void Test1()
{
  BinaryTreeNode* pNode1 = CreateBinaryTreeNode( 1 );
  BinaryTreeNode* pNode2 = CreateBinaryTreeNode( 2 );
  BinaryTreeNode* pNode3 = CreateBinaryTreeNode( 3 );
  BinaryTreeNode* pNode4 = CreateBinaryTreeNode( 4 );
  BinaryTreeNode* pNode5 = CreateBinaryTreeNode( 5 );
  BinaryTreeNode* pNode6 = CreateBinaryTreeNode( 6 );
  BinaryTreeNode* pNode7 = CreateBinaryTreeNode( 7 );

  ConnectTreeNodes( pNode1, pNode2, pNode3 );
  ConnectTreeNodes( pNode2, pNode4, pNode5 );
  ConnectTreeNodes( pNode3, pNode6, pNode7 );

  Test( "Test1", pNode1, true );

  DestroyTree( pNode1 );
}

// 不是徹底二叉樹,可是平衡二叉樹
//             1
//         /      \
//        2        3
//       /\         \
//      4  5         6
//        /
//       7
void Test2()
{
  BinaryTreeNode* pNode1 = CreateBinaryTreeNode( 1 );
  BinaryTreeNode* pNode2 = CreateBinaryTreeNode( 2 );
  BinaryTreeNode* pNode3 = CreateBinaryTreeNode( 3 );
  BinaryTreeNode* pNode4 = CreateBinaryTreeNode( 4 );
  BinaryTreeNode* pNode5 = CreateBinaryTreeNode( 5 );
  BinaryTreeNode* pNode6 = CreateBinaryTreeNode( 6 );
  BinaryTreeNode* pNode7 = CreateBinaryTreeNode( 7 );

  ConnectTreeNodes( pNode1, pNode2, pNode3 );
  ConnectTreeNodes( pNode2, pNode4, pNode5 );
  ConnectTreeNodes( pNode3, NULL, pNode6 );
  ConnectTreeNodes( pNode5, pNode7, NULL );

  Test( "Test2", pNode1, true );

  DestroyTree( pNode1 );
}

// 不是平衡二叉樹
//             1
//         /      \
//        2        3
//       /\         
//      4  5        
//        /
//       6
void Test3()
{
  BinaryTreeNode* pNode1 = CreateBinaryTreeNode( 1 );
  BinaryTreeNode* pNode2 = CreateBinaryTreeNode( 2 );
  BinaryTreeNode* pNode3 = CreateBinaryTreeNode( 3 );
  BinaryTreeNode* pNode4 = CreateBinaryTreeNode( 4 );
  BinaryTreeNode* pNode5 = CreateBinaryTreeNode( 5 );
  BinaryTreeNode* pNode6 = CreateBinaryTreeNode( 6 );

  ConnectTreeNodes( pNode1, pNode2, pNode3 );
  ConnectTreeNodes( pNode2, pNode4, pNode5 );
  ConnectTreeNodes( pNode5, pNode6, NULL );

  Test( "Test3", pNode1, false );

  DestroyTree( pNode1 );
}


//               1
//              /
//             2
//            /
//           3
//          /
//         4
//        /
//       5
void Test4()
{
  BinaryTreeNode* pNode1 = CreateBinaryTreeNode( 1 );
  BinaryTreeNode* pNode2 = CreateBinaryTreeNode( 2 );
  BinaryTreeNode* pNode3 = CreateBinaryTreeNode( 3 );
  BinaryTreeNode* pNode4 = CreateBinaryTreeNode( 4 );
  BinaryTreeNode* pNode5 = CreateBinaryTreeNode( 5 );

  ConnectTreeNodes( pNode1, pNode2, NULL );
  ConnectTreeNodes( pNode2, pNode3, NULL );
  ConnectTreeNodes( pNode3, pNode4, NULL );
  ConnectTreeNodes( pNode4, pNode5, NULL );

  Test( "Test4", pNode1, false );

  DestroyTree( pNode1 );
}

// 樹中只有1個結點
void Test5()
{
  BinaryTreeNode* pNode1 = CreateBinaryTreeNode( 1 );
  Test( "Test6", pNode1, true );

  DestroyTree( pNode1 );
}

// 樹中沒有結點
void Test6()
{
  Test( "Test7", NULL, true );
}

int main()
{
  Test1();
  Test2();
  Test3();
  Test4();
  Test5();
  Test6();
 
  return 0;
}

四10、數組中只出現一次的數字

      一個整數數組裏除了兩個數字以外,其餘的數字都出現了兩次。請寫程序找出這兩個只出現

一次的數字。要求時間複雜度是O(n),空間複雜度是O(1)。

#include <iostream>
#include <stdio.h>

// 判斷數字num的第indexBit位是否是1
bool isBit1( int num, unsigned int indexBit )
{
  num = num >> indexBit;
  return ( num & 1 );
}

// 找到num從右邊數起第一個是1的位
unsigned int FindFirstBitIs1( int num )
{
  int indexBit = 0;
  while( ( ( num & 1 ) == 0 ) && ( indexBit < 8 * sizeof( int ) ) )
  {
    num = num >> 1;
    ++indexBit;
  }

  return indexBit;
}

void FindNumsAppearOnce( int data[], int length, int* num1, int* num2 )
{
  if( data == NULL || length < 2 )
    return;
  
  int resultExclusiveOR = 0;
  for( int i = 0; i < length; ++i )
    resultExclusiveOR ^= data[ i ];

  unsigned int indexOf1 = FindFirstBitIs1( resultExclusiveOR );

  *num1 = *num2 = 0;
  for( int j = 0; j < length; ++j )
  {
    if( isBit1( data[ j ], indexOf1 ) )
      *num1 ^= data[ j ];
    else
      *num2 ^= data[ j ];
  }
}

void Test( const char* testName, int data[], int length, int expected1, int expected2 )
{
  if( testName != NULL )
    printf( "%s begins: ", testName );

  int result1, result2;
  FindNumsAppearOnce( data, length, &result1, &result2 );

  if( ( expected1 == result1 && expected2 == result2 ) ||
    ( expected2 == result1 && expected1 == result2 ) )
    printf( "Passed.\n\n" );
  else
    printf( "Failed.\n\n" );
}

void Test1()
{
  int data[] = { 2, 4, 3, 6, 3, 2, 5, 5 };
  Test( "Test1", data, sizeof( data ) / sizeof( int ), 4, 6 );
}

void Test2()
{
  int data[] = { 4, 6 };
  Test( "Test2", data, sizeof( data ) / sizeof( int ), 4, 6 );
}

void Test3()
{
  int data[] = { 4, 6, 1, 1, 1, 1 };
  Test( "Test3", data, sizeof( data ) / sizeof( int ), 4, 6 );
}

int main()
{
  Test1();
  Test2();
  Test3();

  return 0;
}

相關文章
相關標籤/搜索