文章分类 -  《剑指Offer》学习笔记

摘要:输入一个英文句子,翻转句子中的单词顺序,但单词内的字符顺序不变。如“I am a student." 则输出“student. a am I"void Reverse(char* pBegin, char* pEnd){ if( pBegin == NULL || pEnd == NULL) return; while( pBegin < pEnd) { char temp = *pBegin; *pBegin = *pEnd; *pEnd = temp; pBegin++; pEnd--; ... 阅读全文
posted @ 2013-03-08 21:01 没离开过 阅读(123) 评论(0) 推荐(0)
摘要:输入一个递增排序的数组和一个数字是S,在数组中查找两个数,使得它们的和正好是S。bool FindNumbersWithSum(int data[], int length, int sum, int* num1, int* num2){ bool found = false; if( length < 1 || num1 == NULL || num2 == NULL) return found; int ahead= length-1; int behind = 0; while(ahead > behind) { long... 阅读全文
posted @ 2013-03-08 20:41 没离开过 阅读(102) 评论(0) 推荐(0)
摘要:如果某二叉树中的任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。struct BinaryTreeNode { int value; BinaryTreeNode* p_left; BinaryTreeNode* p_right;};bool IsBalanced(BinaryTreeNode* pRoot, int* pDepth){ if( pRoot == NULL) { *pDepth = 0; return true; } int left,right; if(IsBalanced(pRoot... 阅读全文
posted @ 2013-03-08 20:19 没离开过 阅读(133) 评论(0) 推荐(0)
摘要:在字符串中找出第一只出现一次的字符,如输入“abaccdeff“,则输出b。在这里讲解利用哈希表来解决的方法。因为题目简单所有这里的哈希表可以是用ASCII码为键值的数组。下面是代码:char FirstNotRepeatingChar(char* pString){ if( pString == NULL) return '\0'; const int tableSize = 256; unsigned int hashTable[tableSize]; //初始化哈希表 for(int i=0; i < tableSize ;++i ... 阅读全文
posted @ 2013-03-07 21:01 没离开过 阅读(129) 评论(0) 推荐(0)
摘要:我们把只包含因子2,3和5的数称为丑数。求按从小到大的顺序的第1500个丑数。这里讲解一种用空间换时间的解法。int Min(int number1, int number2, int number3){ int min = (number1 < number2) ? number1 : number2; min = (min < number3) ? min: number3; return min;}int GetUglyNumber(int index){ if(index <=0) return 0; int *pUglyNumbers = ... 阅读全文
posted @ 2013-03-07 20:48 没离开过 阅读(116) 评论(0) 推荐(0)
摘要:输入一个整形数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。这题的思想是我们可以从第一个数开始往后加,每加一次前判断当前所有数的和是否为负数,如果是负数则舍弃前面所加,把值赋值为当前值,如果不是负数则直接加上当前值。代码如下:bool g_InvalidInput = false;int FindGreatestSumOfSubArray(int* pData, int length){ if( pData == NULL || length <=0 ) { g_InvalidInput =tr... 阅读全文
posted @ 2013-03-07 20:31 没离开过 阅读(107) 评论(0) 推荐(0)
摘要:输入N个整数,找出其中最小的K个数;这里讲解O(nlogk)的算法,特别适合处理海量数据。我们先创建大小为K的数据容量来存储最小的K个数字,接着我们每次从输入的n个整数中读入一个数。如果容器中已有的数字少于K个,就直接把这次读入的数放入容器中,如果容器中已经有K个数字,那么我们找出这K个数中的最大值与这次读入的数字最比较,如果这次读入的数字比最大值小则替换。从前面分析中我们可以想到这个容器的数据结构最好是个最大堆,我们可以使用STL中的set 和multiset来实现。下面是代码:typedef multiset<int,greater<int> > intSet;ty 阅读全文
posted @ 2013-03-07 13:49 没离开过 阅读(168) 评论(0) 推荐(0)
摘要:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字:这里讲解一个从数组特点找出O(n)的算法。数组中有一个数字出现的次数超过数组长度的一半,也就是说它出现的次数比其他的所有数字出现次数的和还要多。根据这个特点我们得到下面代码:bool CheckMoreThanHalf(int * numbers, int length,int number){ int times =0; for(int i=0; i<length; ++i) { if( numbers[i] == number) times++; } bool i... 阅读全文
posted @ 2013-03-07 13:27 没离开过 阅读(146) 评论(0) 推荐(0)
摘要:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建新的节点,只能调整树中节点指针的指向。由于要求转换后的链表是排好序的,我们可以用中序遍历树的每一个节点。下面是代码:struct BinaryTreeNode{ int value; BinaryTreeNode* p_left; BinaryTreeNode* p_right;};void ConvertNode(BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInList){ if( pNode == NULL) return; ... 阅读全文
posted @ 2013-03-07 13:09 没离开过 阅读(118) 评论(0) 推荐(0)
摘要:在复杂链表中,每个节点除了有一个pNext指针指向下一个节点外,还有一个pSibling指向链表中的任意节点或者NULL.写一个函数ComplexListNode* Clone(ComplexListNode* pHead),完成复制功能。这里介绍一种在不使用辅助空间的情况下实现O(n)的时间效率的算法。总共分为三步:第一步在每个节点N后面创业一个与之想对于的节点N'。让N指向N',而N‘则指向原来N指向的下一个节点。如果原链表为A->B->C->D,则改变后为A->A'->B->B'->C->C'-> 阅读全文
posted @ 2013-03-06 14:35 没离开过 阅读(108) 评论(0) 推荐(0)
摘要:输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。采用前序遍历所有路径。struct BinaryTreeNode{ int value; BinaryTreeNode* p_left; BinaryTreeNode* p_right;};void FindPath(BinaryTreeNode* pRoot, int expectedSum,std::vector<int>& path,int currentSum){ currentSum += pRoot->value; path.. 阅读全文
posted @ 2013-03-06 14:01 没离开过 阅读(119) 评论(0) 推荐(0)
摘要:输入一个整数数组,判断该数组是不是某二叉搜索数的后序遍历的结果。方法是前面提到过的先找到该树的根节点,然后确定左子树和右子树。在后序遍历中根节点就是数组的最后一个树。再根据搜索树的特点,所有左子树的节点比根节点要小,右子树的节点比根节点要大。所以从头依次判断直到一个数比最后那个树要大则该数后面的数应该都要比最后一个数大。例如{5,7,6,9,11,10,8}则根节点为8,前面3个数5,7,6为左子树,9,11,10为右子树。然后再递归判断{5,7,6},{9,11,10}。下面是代码:bool VerifySquenceOfBST(int sequence[], int length){ .. 阅读全文
posted @ 2013-03-06 13:43 没离开过 阅读(92) 评论(0) 推荐(0)
摘要:题目其实就是按层遍历二叉树。可以运用队列来实现。如果一个节点有子节点那么就把子节点放入队列的末尾,接下来从队列的头部取出最早进入队列的节点。void PrintFromTopToBottom(BinaryTreeNode* pTreeRoot){ if( pTreeRoot == NULL) return; std::deque<BinaryTreeNode*> dequeTreeNode ; dequeTreeNode.push_back(pTreeRoot); while( dequeTreeNode.size()) { Binar... 阅读全文
posted @ 2013-03-04 15:03 没离开过 阅读(75) 评论(0) 推荐(0)
摘要:输入一棵二叉树,把它变成它的镜像。这题的思路通过画图就可以很快明白。本人就不画了,有兴趣可以买书来看。这里讲下怎么做。如果一个节点有子节点交换2个节点.....就这么简单。上代码:void MirrorTree(BinaryTreeNode* pRoot){ if(pRoot == NULL) return; if(pRoot->p_left == NULL && pRoot->p_right == NULL) return; BinaryTreeNode* temp = pRoot->p_left; pRoot->p_left = pRoo... 阅读全文
posted @ 2013-03-04 14:43 没离开过 阅读(84) 评论(0) 推荐(0)
摘要:输入2棵二叉树A和B,判断B是不是A的子结构。解决步骤分为2步:第一步找到树A中与树B根节点的值相同的节点R,第二部判断树A中以节点R为根节点的子树是否包含与树B一样的结构。采用递归方法可以得到如下代码:struct BinaryTreeNode{ int value; BinaryTreeNode* p_left; BinaryTreeNode* p_right;};bool DoesTree1HaveTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2){ if( pRoot2 == NULL ) r... 阅读全文
posted @ 2013-03-04 14:32 没离开过 阅读(113) 评论(0) 推荐(0)
摘要:主要也是考察指针的运用,和代码的鲁棒性。直接上代码:ListNode* Merge(ListNode* pHead1, ListNode* pHead2){ if( pHead1 == NULL && pHead2 == NULL) return NULL; if( pHead1 == NULL ) return pHead2; else if(pHead2 == NULL) return pHead1; ListNode* p_merge = NULL; if(pHead1->value < pHead2->value)... 阅读全文
posted @ 2013-03-04 14:14 没离开过 阅读(89) 评论(0) 推荐(0)
摘要:主要考察指针的操作,也没什么好说的,直接上代码:ListNode * ReverseList(ListNode* pHead){ if( pHead == NULL) return NULL; ListNode* pReversedHead = NULL; ListNode* pNode = pHead; ListNode* pPrev = NULL; while( pNode !=NULL ) //注意这里是判断的停止的条件 { ListNode* pNext = pNode->pNext; //存储当前节点的后一个节点 ... 阅读全文
posted @ 2013-03-03 23:27 没离开过 阅读(83) 评论(0) 推荐(0)
摘要:这里只说只遍历一次找到该节点的办法。我们可以定义2个指针指向表头,然后让第一个指针向前k-1步,第二个指针不动。等第一个指针到达该位置后,2个指针同时开始前进,当第一个指针到达链表尾部的时候第二个指针指向的节点就是想要找的节点。类似的我们也可以用这种思想来找链表的中间节点。定义2个指针,一个指针走一次走1步,另一个一次走2步,这样当那个走的快的指针走到链表尾部的时候,慢的指针就指向链表中间了。struct ListNode{ int value; ListNode* pNext;};ListNode* FindKthToTail(ListNode* pHead, unsigned ... 阅读全文
posted @ 2013-03-03 15:19 没离开过 阅读(77) 评论(0) 推荐(0)
摘要:这题可以维护2个指针,第一个指针初始化为数组的第一个数字,它向后移动。第二个指针初始化为数组最后一个数,它向前移动。如果第一个指针指向的是偶数,而第二个指针又指向的是奇数,两者交换,直到2个指针相遇。bool isEven(int n) //奇数返回false,偶数返回true{ return (n&1) == 0;}void Reorder(int *pData,unsigned int length, bool (*func)(int) ){ if( pData == NULL || length == 0) return; int *pBegin = pD... 阅读全文
posted @ 2013-03-03 14:57 没离开过 阅读(113) 评论(0) 推荐(0)
摘要:输入数字n,顺序打印出从1到最大N位的十进制数。如输入3,则打印1,2,3到999.这里设计一个大数问题,如果能很大,大到long long都会溢出,那么改怎么办。最常用的办法是用字符串或者数组来表达大数.接下来一步步来实现。首先解决打印问题,我们用字符串来表示数字,那么假如存着001,002那么我们是要处理前面的0的。void PrintNumber(char* number){ bool isBeginning0 = true; int length = strlen(number); for(int i = 0; i < length; ++i) { ... 阅读全文
posted @ 2013-03-03 14:25 没离开过 阅读(182) 评论(0) 推荐(0)