编程题——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;
}

相关文章
相关标签/搜索