剑指offer
剑指offer是一本名企面试官精讲典型编程面试题宝典,让我们不仅能学到本书的知识,更重要的是学习到解决问题的能力,思考解决问题的方法,这是最宝贵的!
戎·码一生
自信来自实力,改变来自挑战。做一只生活小强。
展开
-
《剑指offer》:[50]树中两个结点的最低公共祖先结点
题目:树中两个结点的最低公共祖先该题目根据条件的不同,所使用的方案也不同。条件一:是二叉搜索树。 方案:这种情况相对来说是最简单的,如果是二叉搜索树,则树里的数据特点比较明显。左边的比根结点小,右边的比根结点大。所以其最低的公共结点就是第一个在这两个输入节点之间的结点。条件二:如果这棵树是一颗普通的树,可能连二叉树都不算,但是有指向父节点的指针。 方案:其实这个原创 2016-06-25 15:32:10 · 1264 阅读 · 0 评论 -
《剑指offer》:[49]把字符串转化成整数
题目:把字符串转换为整数,也就是实现atoi()。 类似还有itoa(),将整数数转化为字符串,相反的过程。此题虽然简单,但是就像高考一样,简单的题不一定能做对,能做对的不一定能得分。好吧,下面来看看一看应该注意的地方。易错点:1、判断字符串是否为NULL的情况(这是对字符串处理最基本得需要注意的地方)。2、如何区分字符串为NULL时返回的0还是字符'0'返回的0。原创 2016-06-25 15:24:13 · 2199 阅读 · 0 评论 -
《剑指offer》:[48]不能被继承的类-单例模式
题目:不能被继承的类 不能继承,一般我们会对构造函数做手脚。不能继承,继承会发生什么,继承的类在创建对象的时候,会自动调用父类的构造函数,如果我们在这里限制让子类不能调用父类的构造和析构就是实现了不能继承,但是也不能影响自己的使用。方案一:思想:设置构造函数和析构函数为私有+新增两方法创建和销毁对象。原因:(1)把构造函数和析构函数设置为私有函数,这样可以防止子类调用构造函数和原创 2016-06-25 11:52:51 · 6901 阅读 · 0 评论 -
《剑指offer》:[47]不用加减乘除做加法
题目:写一个函数,求两个整数的和,要求在函数体内不得使用+-*/四则运算。方案一:位运算。第一步:将数据转换为二进制,只将各位进行相加,不计算进位。第二步:做进位看进位的是多少;第三步:将第一步和第二部的结果相加。具体分析如下图:具体试下代码如下:#include using namespace std;int Add(int a,int b){ i原创 2016-06-25 11:42:36 · 1892 阅读 · 0 评论 -
《剑指offer》:[46]求1+2+3+...+n
题目:求1+2+3+4+.....+n,要求不能使用除法,for,while,if,else,switch,case等关键字及条件判断语句(A?B:C)。 看似一些不可能的问题,主要是考察我们的发散思维的能力,发散思维的特点是思维活动的多向性和变通性,也就是我们在思考问题时注重运用多思路、多方案、多途径第解决问题。像1+2+3+...+n的解决方法关键就在找到不用上述关键字如何实现递归原创 2016-06-25 11:38:50 · 1884 阅读 · 0 评论 -
《剑指offer》:[45]圆圈中最后剩下的数字(约瑟夫(Josephuse)环问题)
题目:0,1,2,3....N-1这N个数排成一个圆圈,从0开始每次从这个圆圈里删除第M个数字。求出这个圆圈里最后一个剩下的数字。例如0,1,2,3,4这五个数组成一个圆圈,从0开始每次删除第三个数,最后剩下的就是3.方案一:链表模拟环。这里我们将采用链表的数据结构来描述和解决问题。很明显其时间复杂度为O(M*N),空间复杂度为O(N),(M为删除的第几个元素);具体分析过程如下;原创 2016-06-25 11:33:54 · 2046 阅读 · 0 评论 -
《剑指offer》:[44]扑克牌的顺子
题目:从扑克牌里随机抽出5张牌,判断是不是一个顺子,即这五张牌是不是连续的。2-10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成是任意的数字。 分析:这里我们需要将扑克牌的背景抽象成计算机语言。首先,因为扑克牌也是数字,所以我们并不陌生,可以把5张牌看成由5个数字组成的数组。大小王看成是任意的数字,我们可以用0来表示,这样我们就用整形的数字表示了所有的牌。这样简原创 2016-06-25 11:28:48 · 1501 阅读 · 0 评论 -
《剑指offer》:[43]N个骰子的点数
题目:把N个骰子扔在地上,所有骰子朝上一面的点数之和为S,输入N,打印出S的所有可能的值出现的概率。分析:对于6点的N个骰子来讲,其和S的最小值为N,最大值为6N。要得到和S出现的概率,就得得到和S出现的次数,然后用某一S出现的次数/S的所有可能性=S出现的概率。对于骰子进行全排列,我们很容易知道S的所有可能性为:6^N。那么问题来了,怎么计算出S出现的次数呢?方案一:递归法。由于原创 2016-06-25 11:22:39 · 1946 阅读 · 0 评论 -
《剑指offer》:[42-1]左旋转字符串
题目二:字符串的左旋转操作是把字符串前面的若干个字符转移到字符串尾部。请定义一个函数实现字符串左旋转功能。比如输入字符串"youareonly"和数字6,该函数将返回"onlyyouare"。由于有了面试【42】的经验和思路,我们可以这样来解决该问题。用三次翻转:第一步:把整个字符串分为两个部分,前N个要移动的字符和剩下的字符,先翻转前N个字符;"erauoyonly";第二步:再原创 2016-06-19 16:29:25 · 2028 阅读 · 0 评论 -
《剑指offer》:[42]翻转英文中单词顺序
题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。对字符串的操作,主要问题:一定要注意字符串为NULL和访问越界的情况!再就是找'\0'.例如输入字符串;"I love you.",经过翻转就变成:"you. love I"。看出来了吗,故意的,(不论语法)呵呵!方案一:两次翻转法。两次翻转法就是先对整个字符串进行翻转:".u原创 2016-06-19 16:27:05 · 2572 阅读 · 2 评论 -
《剑指offer》:[41-1]和为S的连续整数序列
输入一个正数S,打印出所有和为S的连续正数序列(至少含有两个数)。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出连续序列:1-5,4-6,7-8这三个序列.方案一:时间复杂度为O(N*N)。通过循环来求解。效率较低,不在多赘述。方案二:有了【41】的的经验方法后,我们可以用这样一种方法来得到连续整数序列。时间复杂度为O(N)。我们以S=9为例来分析其过程原创 2016-06-19 16:23:26 · 1405 阅读 · 0 评论 -
《剑指offer》:[41]数组中和为S的两个数
题目:输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的它们的和正好是S。如果有多对数字的和等于S,输出其中的一对即可。例如输入数组{1,2,4,7,11,15}和数字15.由于4+11=15,因此输出4和11。方案一:时间复杂度为O(N*N)。顺序查找法,固定一个数,然后和剩余的N-1个数做和,看和是否为S;如没有,将固定的数下移一个,再与N-2个数字做和,看是否相等。很明显,原创 2016-06-19 16:19:56 · 2049 阅读 · 0 评论 -
《剑指offer》:[40]数组中只出现一次的数字
题目:一个整型数组里除了两个数字外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度为O(N),空间复杂度为O(1)。例如输入数组{2,4,3,6,3,2,5,5},因为只有4和6在这个数组里出现了一次,所以最后输出的是4,6。 分析:因为题目要求的时间复杂度和空间复杂度分别为:O(N)和O(1)。所以这个题目不能借助辅助空间,那么也就是要在一次遍历后就原创 2016-06-19 16:16:03 · 1526 阅读 · 0 评论 -
《剑指offer》:[39-1]判断是否为平衡二叉树
题目:输入一棵二叉树的结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。上图中的二叉树就是一棵平衡二叉树。分析:有了求二叉树深度的思路后,我们很快就能找到求解该问题的方法,就是从根结点开始开始判断其左右子结点的深度之差是否为1。如果从根结点开始到叶子结点的每一个结点的左右子树的深度相差都不超过1,则说明该二叉树是平衡二叉树。但是其原创 2016-06-19 16:02:50 · 1593 阅读 · 0 评论 -
《剑指offer》:[39]求解二叉树的深度
题目:输入一棵二叉树的根结点,求该树的深度。从根结点到叶子结点一次经过的结点(含根、也结点)形成树的一条路径,最长路径的长度为树的深度。例如下图中的二叉树,其深度根结点到叶子结点:1->2->5->7,该条路径的长度为4,所以该二叉树的深度为4 。方案:递归方法。时间复杂度大于O(N)。 在面试题25中,我们讨论了如何用容器来记录一个条路径及求路径的和的情况,但是该方法的代码量比较原创 2016-06-19 15:57:36 · 1528 阅读 · 0 评论 -
《剑指offer》:[38]数字在排序数组中出现的次数
“沟通、学习能力就是看面试者能否清晰、有条理地表达自己,是否会在自己所得到的信息不够的情况下主动发问澄清,能否在得到一些暗示之后迅速做出反应纠正错误” ---陈黎明(MSo原创 2016-06-19 15:53:23 · 1529 阅读 · 0 评论 -
《剑指offer》:[37]如何得到链表环的入口地址
题目:如何得到链表环的入口结点方案:分两步走:第一步:先要找到链表中的环,得到环的结点的个数。可以设置两个指针一个走的比较快,一个比较慢,那么如果链表中存在一个环,那么这两个指针一定会陷入这个环中,快的指针一定会遇到慢的指针,所以很快就能遇到。因为前面有详细讲过,这里不再多介绍。第二步:得到环的个数以后,我们照样可以设置两个指针。第一个指针先前进N(N为环中结点的个数)步,然后和第二个原创 2016-06-19 15:49:11 · 1667 阅读 · 0 评论 -
《剑指offer》:[36]数组中的逆序对
题目:在数组中的两个数字如果前面饿一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如在数组{7,5,6,4}中就有5对,{7,5},{7,6},{7,4},{5,4},{6,4}。方案一:最直接的方法就是顺序扫描每个数字,然后和后面的数字进行比较,如果前一个比后一个小,则说明它们是逆序的,如以上的5组都是逆序的。计数器+1;每个数字和后面比原创 2016-06-11 21:06:36 · 1177 阅读 · 0 评论 -
《剑指offer》:[35]第一次出现且只出现一次的字符
题目:在字符串中查找第一次出现且只出现一次的字符。如输入“ababkdcdycghis”,则输出‘k’。方案一:最直接的方法就是,从字符串的第一个字符开始,顺序扫描和后面的字符进行比较,如果没有发现重复的字符,则说明该字符是第一次出现。由于每个字符都需要和后面的O(N)字符进行比较,所以其时间复杂度为O(N^2)。方案二:时间复杂度为O(N)。由于题目和字符出现的次数有关,所以我们原创 2016-06-11 21:01:10 · 1350 阅读 · 0 评论 -
《剑指offer》:[34]丑数的判断与查找
题目:我们把只包含因子2,3,5的数称为丑数(Ugly Number)。求按从小到大的顺序的第1500个丑数。例如6,8都是丑数,但14不是,因为它包含因子7.习惯上我们把1当作第一个丑数。方案一:所谓一个数m是n的因子的意思是n能被m整除。那么根据丑数的定义,丑数只能被2,3,5整除,如果一个数能被2整除我们就连续除以2,如果能被3整除我们就连续除以3,如果能被5整除,我们就连续除以5。原创 2016-06-11 20:28:32 · 1001 阅读 · 0 评论 -
《剑指offer》:[33]把数组排成最小的数
题目:输入一个正整数数组,把数组里所有的数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这3个数字能排成的最小的数字是321323.这里由于是打印数组里所偶元素所能组成的最小的一个值,如果数组非常大,则有可能溢出,所以这是一个大数问题。大数问题的解决方案是数组或者字符串。这里我们将其转换为字符串。转规则:两个数字m和n能拼接成mn和nm原创 2016-06-10 19:14:16 · 671 阅读 · 0 评论 -
《剑指offer》:[32]从1到n整数中1出现的次数
题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12共有1,10,11,12这四个数有1出现,且出现为5次。方案一:对每一个数字进行统计1的个数,然后相加。统计的方法就是对数取余法,看个位数上是否为1,。如果数大于10,则除10再取余数,看是否为1.该方法的缺点是:如果输入的n比较大,则计算量比较大。对于N个数,每个数有logN位,则其时间复杂度为原创 2016-06-10 19:11:42 · 867 阅读 · 0 评论 -
《剑指offer》:[31]连续子数组的最大和及子序列的值
题目:输入一个整形数组,数组里有整数也有负数。数组中一个或连续多个整数组成一个子数组。求所有子数组的和的最大值和其序列的值。要求时间复杂度为O(N)。例如输入数组为{1,-2,3,10,-4,7,2,5},最后输出的最大该子数组的和为18。方案一:最直观的方法就是列举出数组中所有的子数列,然后对应的每个子数列进行求和。最后再找出最大的一个。对于n个元素的数组,有n(n+1)/2 个子数列。原创 2016-06-10 19:05:03 · 1508 阅读 · 2 评论 -
《剑指offer》:[30]最小的K个数问题
题目:输入N个整数,找出其中最小的k个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4.方案一:就是先对数组进行排序,然后输出前K个数字。时间复杂度为O(N*logN)方案二:根据[29]中数字超过一半的启发,我们可以用基于快速排序的思想,对其进行划分,时间复杂度为O(N)。找出前K小个元素,我们只需要利用Partion函数将小于X的前k个元素移动到X原创 2016-06-09 21:51:27 · 851 阅读 · 0 评论 -
《剑指offer》:[29]数组中出现数字超过一半的数字
对于一半的算法,如果能从额外空间消耗、平均时间复杂度和最差时间复杂度等方面分析问题,可以体现一个dev较好的编程素质和能力。-----刘景勇题目:数组中有一个数字出现的次数超过数组长度的一般,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2.方案一:先排序,后判断。因为数组没有排序,所以我们先原创 2016-06-09 21:45:50 · 794 阅读 · 0 评论 -
《剑指offer》:[28]字符串的全排列问题
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串:abc,acb,bac,bca,cab,cba.对于这样的题目,我可以将问题进行分解。把一个字符串看成两个部分。第一部分为它的第一个字符;第二部分为它的后面的所有字符。 首先求出所有可能在第一个位置的字符,即把第一个字符和后面的每个字符一次交换,得到所有可能在原创 2016-06-09 21:39:56 · 928 阅读 · 0 评论 -
《剑指offer》:[27]二叉搜索树与双向链表的转化过程
题目:输入一课二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。因为树的结构和循环链表的结构十分类似,所以使它们之间的转换成为了可能。具体方法:原先指向左子结点的指针调整为链表中指向前一节点的指针;原先指向右子结点的指针调整为链表中指向后一个结点的指针。因为要求转换之后的链表时排好序的,所以我们可以借助中序遍历。当遍历的时候我原创 2016-06-09 21:36:39 · 710 阅读 · 0 评论 -
《剑指offer》:[26]复杂链表的复制
题目;请实现函数ComplexListNode *Clone(ComplexListNode *pHead),复制一个复杂链表。在复杂链表中,每一个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pString指向链表中的任意结点或者NULL。复杂链表的结构如下:struct ComplexList{int data;ComplexList *pNext;Co原创 2016-06-09 21:27:17 · 669 阅读 · 0 评论 -
《剑指offer》:[25]二叉树中和为某一值的路径
题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。分析如下:例如上图和整数18。第一条路径8,4,6。第二条路径8,10。这里需要明确一个概念:路径就是从根节点出发到叶子结点。一定是到叶子结点结束,而不是中间的某个结点。这就要求我们需要从根节点开始遍历,前中后三种遍历中也只有前序遍历是首先原创 2016-06-09 21:23:14 · 1165 阅读 · 0 评论 -
《剑指offer》:[24]判断一个序列是否为二叉树的后序遍历序列
题目:输入一个整数,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否返回false。假设输入的数字互不重复。在后续遍历中,最后一个数字是根结点,将数组中的数字分为两部分:第一部分是左子树的值,它的值都比根结点小;另一部分是右子树的值,它的值都比根结点大;以上面的二叉树为例:后续遍历[3,6,4,10,14,12,8]的最后一个结点是8,所以在这个数组中,3,6原创 2016-06-09 21:18:56 · 1753 阅读 · 0 评论 -
《剑指offer》:[23]从上往下打印二叉树
题目:从上往下打印二叉树此题实质是考察树的遍历算法,只是这种遍历不是我们熟悉的前、中、后序遍历,而是我们的层次遍历。其实也很简单。分析如下: 按层打印毫无疑问,我们需要从根节点开始,然后依次打印其子节点,为了能保证能打印其子节点,我们应该先保存其两个子节点。如上图先打印根结点8,然后保存其左右结点4,12;然后再打印4,接着将3,6结点依次放入容器中;接着结原创 2016-06-09 21:12:33 · 812 阅读 · 0 评论 -
《剑指offer》:[22]如何判断一个序列是否为栈的弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压栈序列,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。判断一个序列是否是某个栈的弹出顺序的步骤是:(1)如果下一个弹出的数字刚好再栈顶,那么弹出该数字;(2)如果下一个原创 2016-06-07 09:51:53 · 2099 阅读 · 0 评论 -
《剑指offer》:[21]包含min函数的栈
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min,push及pop的时间复杂度都是O(1)。 碰见这个问题,我们的第一直觉就是用一个变量存储最小的元素,但是用一个变量够吗?答案是否定的。因为当我们得到最小的元素后如果要得到次小的元素呢?显然又傻了.所以我们需要一个辅助栈来保存栈内的每一时刻的最小元素。这样不管何时何地你想要都可以得到。不原创 2016-06-07 09:48:14 · 489 阅读 · 0 评论 -
《剑指offer》:[20]顺时针打印数组
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如:如果输入如下矩阵:则依次打印出:1,2,3,4,5....25; 1,2,3,4,5等等;具体是实现代码如下:#include using namespace std;int arr[5][5]={1,2,3,4,5, 16,17,18,19,6, 15,24,25,20,7, 14,原创 2016-06-07 09:42:06 · 770 阅读 · 0 评论 -
《剑指offer》:[19]二叉树的镜像
对于比较复杂的算法和设计,一般来讲最好是在开始写代码前讲清楚思路和设计,举个例子或者画图都是很好的方法!-----尧敏题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。树的镜像对于很多人来说是一个新的概念,但是只要听说过一次就会发现其实很简单:就是将树以根结点为对称轴进行左右翻转。为了直观的了解,图示树(A)的镜像如下:求二次函数镜像的过程:我们先前序遍历这棵树的每原创 2016-06-07 09:37:34 · 576 阅读 · 0 评论 -
《剑指offer》:[18]如何判断树B是树A的子结构
题目:输入两棵二叉树A和B,判断B是不是A的子结构。和链表相比,树中的指针更多更复杂,所以需要格外的小心!实例如下:判断A树中是否包含B树。具体方法是先遍历A树,看A树中是否有B树的根结点。如果有再看该结点是否含有和B树一样的结构!如果没有特殊的要求,我们一般采用递归的方式实现。具体实现代码如下:#include using namespace std;struct原创 2016-06-07 09:33:27 · 1182 阅读 · 0 评论 -
《剑指offer》:[17]调整数组顺序使奇数位于偶数面前
题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。方案一:顺序查找。如果发现一个偶数,则将其移动到数组末尾,将其他的元素向前移动。记住第一个元素,当第二次查找到该元素的时候,就停止,此时,已将所有的偶数移动到了数组的后半段。由此可以看出,每次需要移动n-1个数数字,所以其时间复杂度为O(N^2)。这种方案我们也多次说过,原创 2016-06-05 19:51:08 · 570 阅读 · 0 评论 -
《剑指offer》:[16]打印1到最大的N位数
题目:输入数字N,按顺序打印从1到最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的三位数即:999.乍一看这个题目很简单,我们很快就会写出下面的代码:void onetoN(int n){ int number=1; for(int i=0;i<n;i++) { number*=10; } for(int i=1;i<number;i++) { cout原创 2016-06-05 15:20:00 · 548 阅读 · 0 评论 -
《剑指offer》:[15]实现指数函数:x的y次方
“最不能容忍的功能错误,忽略边界情况。必须保证功能测试、边界测试、负面测试以及性能测试” --尹彦(Intel)问题:数值的整数次方实现double(double base,int exponent),求base的expo原创 2016-06-04 17:03:24 · 1361 阅读 · 0 评论 -
《剑指offer》:[14]位运算以及求二进制中1的个数
位运算是把数字用二进制表示之后,对每一位上的0或者1的运算。二进制及其位运算是现代计算机学科的基石,很多底层的技术都离不开位运。 下面主要介绍几种常见的位运算1、按位与运算符(&)参加运算的两个数据,按二进制位进行“与”运算。运算规则:两位同“1”为“1”,否则为0; 即: 0&0=0; 0&1=0; 1&0=0; 1&1=1;例如:原创 2016-06-04 14:23:53 · 1328 阅读 · 0 评论