![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
剑指Offer学习笔记
文章平均质量分 66
Citronnelle2
这个作者很懒,什么都没留下…
展开
-
《剑指Offer》学习笔记--面试题47:不用加减乘除做加法
题目:写一个函数,求两个整数之和,要求在函数体内不得使用+,-,*,/四则运算。面试的时候被问到这个问题很多人在想:四则运算都不能用,那还能用什么啊?可问题总是要解决的,我们只能打开思路去思考各种可能性。首先可以分析人们是如何做十进制加法的,比如如何得出5+17=22这个结果的。实际上,我们可以分成三步进行:第一步只做各位相加不进位,此时相加的结果是12;第二步做进位,5+7中有进位,进位的值原创 2015-05-15 10:21:52 · 352 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题21:包含min函数的栈
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push及pop的时间复杂度都是O(1)。看到这个问题,我们第一个反应可能是每次压入一个新元素进栈,将栈里的所有元素排序,让最小的元素位于栈顶,这样就能在O(1)的时间得到最小元素。但这种思路不能保证最后压入栈的元素能够先出栈,因此这个数据结构已经不是栈了。我们接着想到在栈里添加一个成员变量原创 2015-05-10 13:50:52 · 281 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题9:斐波那契数列
题目一:写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。斐波那契数列数列的定义如下:公式f[n]=f[n-1]+f[n-2],且f[1]=1,f[2]=1。效率很低的递归算法,面试官都不会喜欢long long Fibonacci(unsigned int n){ if(n <= 0){ return 0; } if(n == 1){ return原创 2015-05-06 17:05:11 · 311 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题14:调整数组顺序使奇数位于偶数前面
题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。如果不考虑时间复杂度,最简单的思路应该是从头到尾扫描这个数组,没碰到一个偶数时,拿出这个数字,并把这个数字后面的所有数字往前移动一位。挪完之后在数组的末尾有一个空位,这时把该偶数放入这个空位。由于碰到一个偶数就需要移动O(n)个数字,因此总的时间复杂度是O(n^2)。但是,原创 2015-05-08 11:04:36 · 378 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题15:链表中倒数第k个结点
题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头开始它们的值依次是1、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。链表结点定义如下:struct ListNode{ int m_nValue; ListNode* m_pNext;};为了实现只遍历链表一次就能够原创 2015-05-08 12:23:25 · 326 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题16:反转链表
题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。链表结点定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};解决与链表相关的问题总是有大量的指针操作,而指针操作的代码总是容易出错的。在实际的软件开发周期中,设计的时间通常不会比编码的时间短。在面试的时候我们不要急于动手写代码,而是一开始仔细原创 2015-05-08 13:24:25 · 317 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题18:树的子结构
题目:输入两颗二叉树A和B,判断B是不是A的子结构。二叉树节点定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;};要查找树A中是否存在和树B结构一样的子树,我们可以分成两步:第一步在树A中找到和B的根结点的值一样的结点R,第二步原创 2015-05-08 15:35:49 · 325 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题19:二叉树的镜像
题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。二叉树结点的定义如下:struct BinaryTreeNode{ int m_nValue; BianryTreeNode* m_pLeft; BianryTreeNode* m_pRight;};树的镜像对很多人来说是一个新的概念,我们未必能够一下子想出求解树的镜像的方法。为了能够形成直观的印象,我们可原创 2015-05-08 18:05:11 · 322 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题20:顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如:如果输入如下矩阵:1 2 3 45 6 7 89 10 11 1213 14 15 16则依次打印出数字1,2原创 2015-05-08 18:23:59 · 397 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题22:栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不等。例如序列1,2,3,4,5是某栈的压入序列,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。解决这个问题很直观的想法就是建立一个辅助栈,把输入的第一个序列中的数字一次压入该辅助栈,并按照第二个序列的顺序依次从该栈中弹出数原创 2015-05-10 14:41:54 · 334 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题30:最小的k个数
题目:输入n个整数,找出其中最小的k个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。解法一:O(n)的算法,只有当我们可以修改输入的数组的时候可用从解决面试题29“数组中出现次数超过一半的数字”得到了启发,我们同样可以基于Partition函数来解决这个问题。如果基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数字原创 2015-05-11 19:29:43 · 377 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题23:从上往下打印二叉树
题目:从上往下打印二叉树的每个结点,同一层的结点按照从左到右的顺序打印。二叉树结点的定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;};这道题实质是考察树的遍历算法,只是这种遍历不是我们熟悉的前序,中序或者后序遍历。由于我们不原创 2015-05-10 19:27:17 · 256 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题24:二叉搜索树的后序遍历
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。分析,在后序遍历得到的序列中,最后一个数字是树的根结点的值。数组中前面的数字可以分为两部分:第一部分是左子树结点的值,它们都比根结点的值小;第二部分是右子树结点的值,它们都比根结点的值大。以数字{5,7,6,9,11,10,8}为例原创 2015-05-10 19:57:03 · 333 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题25:二叉树中和为某一直的路径
题目:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶节点所经过的结点形成一条路径。二叉树结点定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;};一般的数据结构和算法的教材都原创 2015-05-10 20:34:13 · 359 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题17:合并两个排序的链表
题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。链表结点定义如下:struct ListNode{ int m_nValue; ListNode* m_pNext;};这是一个经常被各公司采用的面试题。在面试过程中,我们发现应聘者最容易犯两种错误:一是在写代码之前没有对合并的过程想清楚,最终合并出来的链表要么中间断开了,要么并没有做到原创 2015-05-08 15:10:30 · 369 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题13:在O(1)时间删除链表结点
题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。链表结点与函数的定义如下:struct ListNode{ int m_nValue; ListNode* m_pNext;};void DeleteNode(ListNode **pListHead, ListNode *pToBeDeleted);在单向链表中删除一个结点,最常规的做法原创 2015-05-08 10:25:52 · 294 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题12:打印1到最大的n位数
题目:输入数字n,按顺序打印出从1最大的n位十进制数。比如输入3,则打印出1,、2、3一直到最大的3位数及999.跳进面试官的陷阱这个题目看起来很简单。我们看到这个问题之后,最容易想到的办法是先求出最大的n位数,然后用一个循环从1开始逐个打印。于是我们很容易就能写出如下的代码:void Print1ToMaxOfDigits(int n){ int number = 1; int原创 2015-05-07 15:11:42 · 584 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题48:不能被继承的类
题目:用C++设计一个不能被继承的类在c#中定义了关键字sealed,被sealed修饰的类不能被继承。在Java中同样也有关键字final表示一个类型不能被继承。在C++中没有类似于sealed和final的关键字,我们只有自己来实现。常规的解法:把构造函数设为私有函数很多人都能够想到,在C++中子类的构造函数会自动调用父类的构造函数,子类的析构函数也会自动调用父类的析构函数。要想一原创 2015-05-15 10:46:11 · 438 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题49:把字符串转换成整数
题目:实现一个函数StrToInt,实现把字符串转换成整数这个功能,不能使用atoi或者其他类似的库函数。这看起来是很简单的题目,实现基本功能 ,大部分人都能用10行之内的代码解决。可是,当我们要把很多特殊情况即测试用例都考虑进去,却不是件容易的事。解决数值转换问题本身并不难,但我希望在写转换数值的代码之前,应聘者至少能把空指针,空字符串"",正负号,溢出等方方面面的测试用例都考虑到,并且在写原创 2015-05-15 12:44:32 · 470 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题50:树中两个结点的最低公共祖先
题目:求树中两个结点的最低公共祖先,此树不是二叉树,并且没有指向父节点的指针。bool GetNodePath(TreeNode* pRoot, TreeNode* pNode, list&path){ if(pRoot == pNode) return true; path.push_back(pRoot); bool found = false; vector::iter原创 2015-05-15 14:35:58 · 414 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题51:数组中重复的数字
题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3.解决这个问题的一个简单的方法是先把输入的数组排序。从排序的数组中找出重复的数字时间很容易的事情,只需要从头到尾扫描排序后的数组就原创 2015-05-15 15:01:06 · 544 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题52:构建乘积数组
题目:给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[I-1]*A[I+1]*...*A[n-1]。不能使用除法。void multiply(const vector& array1, vector& array){ int length1 = array1.size(); int length原创 2015-05-15 15:33:21 · 475 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题55:字符流中第一个不重复的字符
题目:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符“go”时,第一个只出现一次的字符是‘g’。当从该字符流中读出前六个字符“google”时,第一个只出现1次的字符是"l"。字符只能一个接着一个从字符流中读出来。可以定义一个数据容器来保存字符在字符流中的位置。当一个字符第一次从字符流中读出来时,把它在字符流中的位置保存到数据容器里。当这个字符再次从字原创 2015-05-17 12:35:31 · 459 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题62:序列化二叉树
题目:请实现两个函数,分别用来序列化和反序列化二叉树。通过分析解决前面的面试题6.我们知道可以从前序遍历和中序遍历构造出一棵二叉树。受此启发,我们可以先把一棵二叉树序列化成一个前序遍历序列和一个中序序列,然后再反序列化时通过这两个序列重构出原二叉树。这个思路有两个缺点。一个缺点是该方法要求二叉树中不能用有数值重复的结点。另外只有当两个序列中所有数据都读出后才能开始反序列化。如果两个遍历序列原创 2015-05-17 15:20:18 · 476 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题7:用两个栈实现队列
题目:用两个栈实现一个队列。队列的声明如下,请实现它的函数appendTail和deleteHead,分别完成在队列尾部插入节点和在队列头部删除节点的功能。template class CQueue{public: CQueue(void); ~CQueue(void); void appendTail(const T& node); T deleteHead();pri原创 2015-05-06 15:08:39 · 368 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题3:二维数组中的查找
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。例如下面的二维数组就是每行、每列都递增排序。如果在这个数组中查找数字7,则返回true;如果查找数字5,由于数组不含有该数字,则返回false。1 2 8 92 4原创 2015-05-04 15:17:38 · 398 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题5:从尾到头打印链表
题目:输入一个链表的头结点,从尾到头反过来打印出每个节点的值。链表节点定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};解题思路: 首先想到的是把链表翻转过来,然后再按顺序输出。但是这个方法会改变原来链表的结构,通常打印是一个只读操作,所原创 2015-05-04 21:32:11 · 356 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题10:二进制中1的个数
题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1.因此如果输入9,该函数输出2。可能引起死循环的解法这是一道很基本的考察二进制和位运算的面试题。题目不是很难,面试官提出问题后,我们很快就能形成一个基本的思路:先判断整数二进制表示中最右边一位是不是1。接着把输入的整数右移一位,此时原来处于从右边数起的第二位被移到最右边了,再判断是不原创 2015-05-06 19:20:56 · 315 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题4:替换空格
题目:请实现一个函数,把字符串中的每个空格替换成"%20"。例如输入"We are happy",则输出"We%20are%20happy"。在网络编程中,如果URL参数中含有特殊字符,如空格、‘#’等,可能导致服务器端无法获得正确的参数值。我们需要将这些特殊符号转换为服务器识别的字符。转换规则是在‘%’后面跟上ASCII码的两位十六进制的表示。比如空格的ASCII码是32,即十六进制的0x2原创 2015-05-04 15:49:28 · 423 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题11:数值的整数次方
题目:实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。我们都知道在C语言的库中有一个pow函数可以用来求乘方,本题要求实现类似于pow的功能。要求实现特定库函数(特别是处理数值和字符串的函数)的功能,是一类常见的面试题。自以为题目简单的解法由于不需要考虑大数问题,这道题看起原创 2015-05-07 13:04:29 · 287 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题26:复杂链表的复制
题目:请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任意结点或者NULL。结点的C++定义如下:struct ComplexListNode{ int m_nValue; Comp原创 2015-05-11 12:56:31 · 409 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题27:二叉搜索树与双向链表
题目:输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。二叉树结点定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;};在二叉树中,每个结点都有两个指向子结点的指针原创 2015-05-11 13:57:34 · 318 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题28:字符串的排列
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba.我们求整个字符串的排列,可以看成两步:首先求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换。第二步固定第一个字符,求后面所有字符的排列。这个时候我们仍把后面的所有字符分成两部分:后面的第一个字原创 2015-05-11 15:38:39 · 335 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题46:求1+2+...+n
题目:求1+2+...+n,要求不能使用乘除法,for,while,if,else,switch,case等关键字及条件判断语句(A?B:C).这个问题本身没有太多实际意义,因为在软件开发中不可能有这么苛刻的限制。但不少面试官认为这是一道不错的能够考察应聘者发散思维能力的题目,而发散思维能够反映出应聘者的知识宽度,以及对编程相关技术理解的深度。通常求1+2+...+n除了用公式n(n+1)原创 2015-05-14 22:02:52 · 475 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题56:链表中环的入口结点
题目:一个链表中包含环,如何找出环的入口结点?可以用两个指针来解决这个问题。先定义两个指针P1和P2指向链表的头结点。如果链表中环有n个结点,指针P1在链表上向前移动n步,然后两个指针以相同的速度向前移动。当第二个指针指向环的入口结点时,第一个指针已经围绕着环走了一圈又回到了入口结点。剩下的问题就是如何得到环中结点的数目。我们在面试题15的第二个相关题目时用到了一快一慢的两个指针。如果两个原创 2015-05-17 13:11:15 · 553 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题57:删除链表中重复的结点
题目:在一个排序的链表中,如何删除重复的结点?解决这个问题的第一步是确定删除的参数。当然这个函数需要输入待删除链表的头结点。头结点可能与后面的结点重复,也就是说头结点也可能被删除,因此函数函数应该声明为void deleteDuplication(ListNode** pHead),而不是void deleteDuplication(ListNdoe* pHead)。接下来我们从头遍历整个原创 2015-05-17 13:32:46 · 346 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题58:二叉树的下一个结点
题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点?树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父节点的指针。如果一个结点有右子树,那么它的下一个结点就是它的右子树中的左子结点。也就是说右子结点出发一直沿着指向左子结点的指针,我们就能找到它的下一个结点。接着我们分析一个结点没有右子树的情形。如果结点是它父节点的左子结点,那么它的下一个结点就是它的父结点原创 2015-05-17 13:58:00 · 351 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题59:对称的二叉树
题目:请实现一个函数来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。通常我们有三种不同的二叉树遍历算法,即前序遍历、中序遍历和后序遍历。在这三种遍历算法中,都是先遍历左子结点再遍历右子结点。我们是否可以定义一种遍历算法,先遍历右子结点再遍历左子结点?比如我们针对前序遍历定义一种对称的遍历算法,即先遍历父节点,再遍历它的右子结点,最后遍历它的左子结点。我们发现可以原创 2015-05-17 14:17:42 · 404 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题61:按之字形顺序打印二叉树
题目:请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,即第一行按照从左到右的顺序打印,第二层按照从右到左顺序打印,第三行再按照从左到右的顺序打印,其他以此类推。按之字形顺序打印二叉树需要两个栈。我们在打印某一行结点时,把下一层的子结点保存到相应的栈里。如果当前打印的是奇数层,则先保存左子结点再保存右子结点到一个栈里;如果当前打印的是偶数层,原创 2015-05-17 14:57:13 · 433 阅读 · 0 评论 -
《剑指Offer》学习笔记--面试题63:二叉搜索树的第k个结点
题目:给定一棵二叉搜索树,请找出其中的第k大的结点。如果按照中序遍历的顺序遍历一棵二叉搜索树,遍历序列的数值是递增排序的。只需要用中序遍历算法遍历一棵二叉搜索树,就很容易找出它的第k大结点。BinaryTreeNode* KthNodeCore(BinaryTreeNode* pRoot, unsigned int& k){ BinaryTreeNode* target = NULL;原创 2015-05-17 15:50:40 · 436 阅读 · 0 评论