三十一、连续子数组的最大和
输入一个整数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。
求所有子数组的和的最大值。要求时间复杂度为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;
}
三十二、从1到n整数中出现的次数
输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12
这些整数中包含1的数字有1, 10, 11和12, 1一共出现了5次。
#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, 32, 321 },则打印出这3个数字能排成的最小数字321323.
#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;
}
三十四、丑数
我们把只含包含因子2、3和5的数称为丑数(Ugly Number)。求按从小到大的顺序的第
1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7.习惯上我们把1当做丑数。
#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;
}
三十五、第一个只出现一次的字符
在字符串中找出第一个只出现一次的字符。如输入"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;
}
三十六、数组中的逆序对
在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输
入一个数组,求出这个数组中的逆序对的总数。
#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;
}
三十七、两个链表的第一个公共结点
输入两个链表,找出它们的第一个公共结点。
#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;
}
三十八、数字在排序数组中出现的次数
统计一个数字在排序数组中出现的次数。例如输入排序数组{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;
}
三十九、二叉树的深度
输入一颗二叉树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结
点)形成树的一条路径,最长路径的长度为树的深度。
#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;
}
四十、数组中只出现一次的数字
一个整数数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现
一次的数字。要求时间复杂度是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;
}
来源:oschina
链接:https://my.oschina.net/u/2537915/blog/718634