三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; }
输入一个整数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; }
输入一个正整数数组,把数组全部数字拼接起来排成一个数,打印能拼接出的全部数字中最小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; }
咱们把只含包含因子二、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; }
在字符串中找出第一个只出现一次的字符。如输入"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; }
输入两个链表,找出它们的第一个公共结点。
#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; }