剑指offer
moses1213
积跬步,至千里;积小流,成江海!
展开
-
剑指offer-面试题3:二维数组中的查找
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。解法:把二维数组看成一个矩形,每次从数组的右上角取出一个数a与整数作比较。如果恰好等于这个整数,则返回真。如果a大于这个整数,则a所在的列都大于整数,删去这一列重新从右上角取一个数作比较。如果a小于整数,则a所在的行都小于整原创 2016-02-29 16:28:14 · 494 阅读 · 0 评论 -
剑指offer-面试题39:二叉树的深度
题目一:输入一颗二叉树的根结点,求该树的深度。从根结点到叶结点一次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。思路:如果根结点存在,那么深度至少为1,接下来求左右子树的深度,很明显用递归算法,最后树的深度就是左右子树中深度较大的加上1.int DepthOfBinaryTree(BinaryTreeNode* pRoot){ if(pRoot == NU原创 2016-04-11 21:31:05 · 598 阅读 · 0 评论 -
剑指offer-面试题38:数字在排序数组中出现的次数
题目:统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4.思路:排序的数组,最直接的想法就是二分查找。但是数字有重复,如果可以找到数字出现的起始位置和终止位置,那么就可以统计数字出现的次数,因此这个问题转化为用二分查找寻找数字出现的第一个位置和最后一个位置的问题。如果取数组的中位数,它等于要查找的数,那么在它原创 2016-04-11 19:44:50 · 429 阅读 · 0 评论 -
剑指offer-面试题37:两个链表中的一个公共结点
题目:输入连个链表,找出它们的第一个公共结点。思路:两个链表,用两个指针这个问题就over了。因为每个结点只有一个m_pNext指针,所以第一个公共结点之后,链表合并成一条线,必然成Y型结构。我们用两个指针从表头开始遍历,但是需要注意的是两个链表的长度可能不一样,为了保持两个指针的同步让指向长一些的链表的指针先走,先走的步数即为两个链表的长度差。然后开始同时移动指针,发现相同的结点即返回结点值原创 2016-04-11 16:26:19 · 332 阅读 · 0 评论 -
剑指offer-面试题36:数组中的逆序对
题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中逆序对的个数。例如在数组{7,5,6,4}中,一共存在5个逆序对,分别是(7,6)、(7,5)、(7,4)、(6,4)和(5,4)。思路:分解这个问题,考虑相邻两个数字构成逆序对的情况。以{7,5,6,4}为例,先分解成{7,5}和{6,4},再分解成长度为1的数组{7},{5},{原创 2016-04-11 15:45:34 · 343 阅读 · 0 评论 -
剑指offer-面试题44:扑克牌的顺子
题目:从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大小王可以看成任意数字。思路:把5张牌看成5个数字的数组,大小王看成0以和其他牌区分。判断是否连续,首选想到对数组排序,如果连续,则相邻的两张牌之间间隔为1,如果间隔大于1,我们可以用0(即大小王)填补空缺,如果0可以补满空缺,则说明5张牌是连续的,反之不连续。原创 2016-04-14 16:38:51 · 570 阅读 · 0 评论 -
剑指offer-面试题43:n个骰子的点数
题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s所有可能的值出现的概率。思路:骰子六个点数,所以n个骰子出现的所有可能有6的n次方种。那么这个问题我们专注于求点数和s可能出现的次数,概率相除就可以了。假设点数和为n,那么最后一粒骰子可能出现1,2,3,4,5,6这六种可能,对于倒数第二颗骰子,如果在它之前的所有点数和为n-1,n-2,n-3,n-4,n-5,n-6,那原创 2016-04-14 11:23:43 · 983 阅读 · 0 评论 -
剑指offer-面试题55:字符流中第一个不重复的字符
题目:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是‘g'。当从该字符流中读出前六个字符"google"时,第一个只出现一次的字符是'l'。思路:这道题和面试题35非常相似,只不过那里是字符串这里变成字符流,动态的返回的只出现一次的结果。仍然采用哈希表来解决这个问题,用大小为256的数组来模拟哈希表,在面试题35那里原创 2016-04-26 21:29:17 · 435 阅读 · 0 评论 -
剑指offer-面试题35:第一个只出现一次的字符
题目:在字符串中找出第一个只出现一次的字符。如输入“abaccdeff",则输出'b'。思路:这道题目不难,遍历一遍统计每个字符出现的次数就完了。作者用的是哈希表,因为只需要统计次数,而且字符只有256中,可以用一个大小为256的数组实现。自己用STL里的map容器也实现了,道理完全一样。//哈希表实现输出第一个只出现一次的字符char FirstNotRepeatingChar(c原创 2016-04-09 20:41:01 · 397 阅读 · 0 评论 -
剑指offer-面试题54:表示数值的字符串
题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、“3.1416”及“-1E-16”都表示数值,但"12e“、”1a3.14"、“1.2.3”、“+-5”及“12e+5.4”都不是。思路:表示数值的字符串遵循如下模式:[sign]integral-digits[.[fractional-digits]][e|E[sign]ex原创 2016-04-26 19:51:20 · 786 阅读 · 0 评论 -
剑指offer-面试题6:重建二叉树
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。解:算法的关键是找出根节点的左子树和右子树。如果算法能求出根节点和左右子树,剩下的递归调用这个算法就可以了。前序遍历的第一个值就是根节点,而中序遍历中左子树就是根节点前面的部分,右子树就是根节点右边的部分,问题得解。下面是代码及测试部分。#include using n原创 2016-03-14 16:08:53 · 315 阅读 · 0 评论 -
剑指offer-面试题8:旋转数组的最小数字
题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.思路:旋转之后的数组实际上可以划分成两个排序的子数组,最小数是两个子树组的分界线,试着用二分查找的方法来寻找最小数。使用指针指向数组的第一个元素和最后一个元素,求两个指针的中值原创 2016-03-20 20:49:08 · 448 阅读 · 0 评论 -
剑指offer-面试题9:斐波那契数列
题目一:写一个函数,输入n,求斐波那契(Fabonacci)数列的第n项。斐波那契数列的定义如下:效率很低的解法:递归long long Fibonacci(unsigned n){ if(n <= 0) return 0; if(n == 1) return 1; return Fibonacci(n-1) + F原创 2016-03-22 22:12:30 · 368 阅读 · 0 评论 -
剑指offer面试题10—二进制中1的个数
题目:请实现一个函数,输入一个整数,输出该数二进制表中1的个数。例如把9表示成二进制是1001,有2位是1.因此如果输入9,该函数输出2。思路:如果二进制位中有一位是1,那么与1与即可返回真值。那么有两种方式统计二进制表1的个数。一种方式是将输入的整数右移,每个位上的数逐个和1与。但是这种方式在输入负数的时候会造成死循环,因为负数在计算机中是以补码的形式存在的,负数右移要在左边补1,所以最后所原创 2016-03-26 20:16:08 · 320 阅读 · 0 评论 -
剑指offer-面试题45:圆圈中最后的数字
题目:0,1,…,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里最后剩下的数字。思路(1):用环形链表模拟圆圈。int LastRemaining(unsigned int n, unsigned int m){ if(n < 1 || m < 1) return -1; unsigned int原创 2016-04-16 16:50:04 · 432 阅读 · 0 评论 -
剑指offer-面试题57:删除链表中重复的结点
题目:在一个排序的链表中,如何删除重复的结点?例如1->2->3->3->4->4->5删除重复结点后为1->2->5。原创 2016-05-02 10:27:20 · 498 阅读 · 0 评论 -
剑指offer-面试题64:数据流中的中位数
题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是就是所有数值排序后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。思路:问题本身不难,关键在于采取哪种数据结构和算法。(1)如果用未排序的数组实现,那么插入的时间复杂度为O(1),查找的时间复杂度为O(n)(半快速排序法);(2)如果是排序的数组,那么插入的时候要维护原创 2016-05-06 20:12:15 · 4103 阅读 · 0 评论 -
剑指offer-面试题56:链表中环的入口结点
题目:一个链表中包含环,如何找出环的入口结点?例如下图的链表中,环的入口结点是结点3。原创 2016-04-27 20:45:34 · 412 阅读 · 0 评论 -
剑指offer-面试题4:替换空格
题目请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。思路我们首先想到的就是从前往后扫描,如果空格,就替换为%20,但是这样需要移动空格后的元素。我们还有一种方法,首先遍历一遍字符串,统计出空格的个数,并可以由此计算出替换之后的字符串的长度。每替换一个空格,长度增原创 2016-02-29 20:41:05 · 354 阅读 · 0 评论 -
剑指offer-面试题25:二叉树中和为某一值的路径
题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的形成一条路径。思路:对于每棵子树,它都是一个求解树中结点值的和为输入整数的所有路径的问题,整数为去除它的父节点的和之后新的值,所以很明显可以用递归的方法求解。那么对于每个结点,怎样判断是否已经是要求的路径呢?题目要求和为整数且是叶结点。作者给出的思路简单粗暴,那就是遍历,不管加原创 2016-04-02 16:36:02 · 551 阅读 · 0 评论 -
剑指offer-面试题58:二叉树的下一个结点
题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点?树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针。思路:举一个例子,容易发现规律。这个问题可以分为两种情况:(1)结点存在右子结点,那么中序遍历的下一个结点就是它的右子结点。(2)结点不存在右子结点,这里又要考虑两种情况:一是结点本身作为左子结点,那么它的下一个结点就是它的父结点;二是结点本身作为原创 2016-05-02 15:35:10 · 640 阅读 · 0 评论 -
剑指offer-面试题7:用两个栈实现队列
题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appenTail和deleteHead,分别完成在队列尾部插入结点和队列头部删除结点的功能。解法:因为栈是后入先出,而队列是先入先出。即出栈的顺序是和入栈的顺序颠倒的,由负负得正很容易想到两个栈可以实现按原先的顺序输出。算法设计:(1)入队的时候总是插入stack1的尾部; (2)出队的时原创 2016-03-17 11:43:23 · 509 阅读 · 0 评论 -
剑指offer-面试题47:不用加减乘除做加法
题目:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。思路:四则运算都不能用只能位运算了。其实第一想法就是位运算,位运算转换成二进制才能看出规律,这步是关键!例如4+7,二进制是101+111,考虑二进制的加法,先不考虑进位,101+111结果是010,很明显各个位上做了异或运算。下一步考虑进位,最低位和最高位都产生了进位,进位的结果是1010,最低位产生的进位左原创 2016-04-23 10:47:05 · 368 阅读 · 0 评论 -
剑指offer-面试题46:求1+2+…+n
题目:求1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。方法一:利用构造函数求解。程序不让使用循环,但是我们可以以另一种方式实现循环,譬如利用构造函数,不断的调用构造函数,函数的执行语句放在构造函数内部,当我们创建n个类的实例,构造函数也就执行了n次。class Temp{public: tem原创 2016-04-22 16:49:59 · 307 阅读 · 0 评论 -
剑指offer-面试题63:二叉搜索树的第K个结点
题目:给定一棵二叉搜索树,请找出其中的第K大的结点。例如下图中的二叉树,按加点数值大小顺序第三个结点的值是4。思路:二叉搜索树的一个重要性质就是它的中序遍历是排序的,因此这道题目只需要用中序遍历算法遍历一棵二叉搜索树,就很容易找出它的第K大结点。中序遍历用递归实现比较容易,但要想清楚的是遍历到一个根结点的时候要做的是什么?中序遍历二叉树打印的时候我们在递归完左子树之后打印根结点,本题目原创 2016-05-06 11:22:54 · 3338 阅读 · 5 评论 -
剑指offer-面试题62:序列化二叉树
题目:请实现两个函数,分别用来序列化和反序列化二叉树。思路:题目的要求似乎不是太清晰,实际上就是用序列来表示一棵二叉树,然后还可以根据这个序列重建二叉树。对于上图中的树,以前序遍历为例,先访问到1,然后2,然后4,4的左右子结点都为空,可以用一个特殊字符替代,譬如用$,所以上图中的二叉树前序遍历表示就是“1,2,4,$,$,$,3,5,$,$,6,$,$"。 重建的时候,访问原创 2016-05-05 17:08:35 · 1698 阅读 · 0 评论 -
剑指offer-面试题61:按之字形顺序打印二叉树
题目:请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。上图按之字形打印的结果为:13 24 5 6 715 14 13 12 11 10 9 8思路:对于奇数层和偶数层,它们的打印顺序是不一样的。打印原创 2016-05-05 11:45:45 · 567 阅读 · 0 评论 -
剑指offer-面试题60:把二叉树打印成多行
题目:从上到下按层打印二叉树,同一层的结点按从左到右的顺序打印,每一层打印到一行。例如,打印下图中的二叉树的结果为: 8 6 10 5 7 9 11思路:前面讲过如何从上往下按层打印二叉树,这里需要加入换行问题。引入两个变量:一个变量表示在当前层中还没有打印的结点数,另一个变量表示下一层结点的数目。原创 2016-05-02 20:49:49 · 467 阅读 · 0 评论 -
剑指offer-面试题59:对称的二叉树
题目:请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。思路:如果一个树是对称的,那么它的前序遍历和它的前序遍历的对称遍历是一致的。所谓前序遍历的对称遍历,即遵循根结点-右子结点-左子结点的遍历顺序,如果属实对称的,那么两种结果应该完全一样。 实际上不按书上的思路也是可以的,先比较根结点的左右子结点,根据每个结点是否存在可以分为几种情况,然原创 2016-05-02 17:14:17 · 421 阅读 · 0 评论 -
剑指offer-面试题11:数值的整数次方
这一节还是挺有收获的,作者首先讲了代码的规范性和完整性。规范性即清晰地书写、清晰的布局、合理的命名,我想这也是对一个优秀的程序员的基本要求。代码的完整性里面提到了几个以前没听说过的概念。确保代码完整性的3个方面:功能测试、边界测试、负面测试。功能测试即考虑普通功能的测试用例,写出的代码要能够满足面试官要求的基本功能,同时考虑问题要全面,不能遗漏。边界测试即程序中可能存在递归和循环。如果是循环,原创 2016-03-27 18:36:42 · 309 阅读 · 0 评论 -
剑指offer-面试题12:打印1到最大的n位数
题目:输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数即999.解法:这道提的陷进在于没有规定最大的n位数的范围,会不会溢出,也就是说我们要考虑大数问题。最常用也是最容易的方法是用字符串或者数组去表达大数。bool increment(char* number){ bool IsOverFlow = false; int TakeOv原创 2016-03-27 20:58:24 · 341 阅读 · 0 评论 -
剑指offer-面试题28:字符串的排列
题目:输入一个字符串,打印出该字符串中字符放入所有排列。例如输入字符串abc,则打印出字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。思路:全排列的问题实际就是交换问题。把问题划分成两个部分,第一个字符和后面的部分,所以这个问题分为两个步骤:(1)考虑第一个字符的所有可能情况,将第一个字符和后面的所有字符交换;(2)考虑第一个字符后面的整体部分,那么这部分原创 2016-04-04 11:27:04 · 672 阅读 · 0 评论 -
剑指offer-面试题26:复杂链表的复制
题目:请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任意结点或者NULL。结点的C++定义如下:struct ComplexListNode{int原创 2016-04-02 20:13:13 · 683 阅读 · 0 评论 -
剑指offer-面试题27:二叉搜索树与双向链
题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点只能调整树中结点指针的指向。思路:对于二叉搜索树,根结点的左子树都比它小,右子树都比它大,如果按照中序遍历那么结点就是排序的,问题的关键是如何修改指针指向。假设左右子树已经排序,那么只要将左子树的尾结点连接上根结点,根结点连接上右子树就可以了。关于怎么连接左右子树,还是有一点技巧的。我们每次连接完成之后都原创 2016-04-03 20:18:45 · 466 阅读 · 0 评论 -
剑指offer-面试题24:二叉搜索树的后序遍历序列
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。思路:如果熟悉二叉搜索树的特征这题就不难解了。复习一下二叉搜索树。对于二叉搜索树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;那么后序遍历的结果就是:根结点排原创 2016-04-01 22:06:43 · 379 阅读 · 0 评论 -
剑指offer-面试题23:从上往下打印二叉树
题目:从上往下打印二叉树的结点,同一层的结点按照从左到右的顺序打印。思路:先打印根结点,那么为了打印根结点的两个子结点,需要一个容器将两个子结点保存起来。然后打印左子树,过程和打印根结点类似,也需要将左子树的左右子结点保存起来。这时候容器里存有根结点的的右子树和左子树的两个子结点。接下来要打印右子树了,需要从容器里取出右子树,由于右子树相比左子树的两个子结点先入容器,先入先出,所以这是一个队列原创 2016-04-01 19:45:38 · 300 阅读 · 0 评论 -
剑指offer-面试题22:栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设入栈的所有数字均不相等。思路:用一个栈来模拟入栈过程。如果弹出序列的元素a不等于栈顶,那么说明它还没有入栈,从压入顺序里将元素a以及它之前的元素全部入栈。如果所有压入顺序中的元素都已入栈还是没有在栈顶找到元素a,说明弹出序列是错误的。如果元素a刚好等于栈顶,直接出栈。最后的过程应该是所有元素都出栈而且原创 2016-04-01 11:36:51 · 306 阅读 · 0 评论 -
剑指offer-面试题18:树的子结构
题目:输入两颗二叉树A和B,判断B是不是A的子结构。思路:第一步在树中找到和B的根结点的值一样的结点R,第二步再判断树A中以R为根结点的子树是不是包含B一样的结构。bool HasSubTree(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2){ bool result = false; if(pRoot1 != NULL &原创 2016-03-30 16:21:09 · 306 阅读 · 0 评论 -
剑指offer-面试题19:二叉树的镜像
题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。思路:镜像即关于一条竖直线对称,可以发现镜像后所有左右子树均互换位置。从根结点的左右子树开始交换它们的位置,那么对于左右子树来说他们成了新的根结点,镜像的过程和上一步完全一样,所以这是一个递归的过程。同时递归在本质上就是一个栈结构,也可以用栈来实现。递归版本:void MirrorRecursively(BinaryTreeNo原创 2016-03-30 21:36:41 · 309 阅读 · 0 评论 -
剑指offer-面试题20:顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。思路:原创 2016-03-31 17:29:15 · 533 阅读 · 2 评论