![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
剑指offer面试题
一个追风的产品经理
这个作者很懒,什么都没留下…
展开
-
实现单例模式
单例模式这个还是比较熟悉的原创 2014-10-28 14:33:20 · 418 阅读 · 0 评论 -
二叉搜索树的后续遍历序列
面试题24:二叉搜索树的后序遍历序列题目:输入一个整数数组,判断数组是不是某二叉搜索树的后序遍历结果,如果是则返回true,否则返回false。假设输入的数组每个数字都不相同。分析:二叉搜索树:所有左子树的结点的值都不大于根结点,右子树则不小于根结点。根据后序遍历二叉树的结果可以知道最后一个元素为根结点,前面的可以分为两部分。一部分比根节点大(右子树),一部分比根结点小(左子树)。然后原创 2015-01-16 10:21:01 · 339 阅读 · 0 评论 -
从上往下打印二叉树
面试题23:从上到下打印二叉树题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。二叉树的结点定义如下:struct BinaryTreeNode{int value;BinaryTreeNode* pLeft;BinaryTreeNode* pRight;}分析:这个题目应该属于比较简单的一类,但是第一次做确实做错了原因太相当然了。从上到原创 2015-01-15 15:19:13 · 266 阅读 · 0 评论 -
二叉树中和为某一值的路径
面试题25:二叉树中和为某一值的路径题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶子结点所经过的结点形成一条路径。二叉树结点的定义如下:struct BInaryTreeNode{int value;BinaryTreeNode* pLeft;BinaryTreeNode* pRight;}分析:用先序遍历原创 2015-01-19 16:36:44 · 344 阅读 · 0 评论 -
旋转数组的最小数字
题目8:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.注意到旋转之后的数组实际上可以划分为两个排序的子数组,而且前面的子数组的元素都大于或者等于后面子数组的元素。我们还可以注意到最小的元素刚好是这两个子数组的分界线。我们试着用二元查原创 2014-12-30 19:26:50 · 280 阅读 · 0 评论 -
斐波那契数列
面试题9:题目一:写一个函数,输入n,求斐波那契数列的第n项,斐波那契数列的定义如下: 0 n=0 f(n) = { 1 n=1原创 2014-12-31 18:15:00 · 384 阅读 · 0 评论 -
二叉搜索树与双向链表
面试题27:二叉搜索树与双向链表题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。比如输入下图的二叉搜索树,则输出转换之后的排序双向链表。分析:从二叉搜索树到有序序列的转换分析,首先二叉搜索的定义:若树不为空则子树也为二叉搜索树,且左子树比根小,右子树比根大。所以递增顺序为:左->根->右。这个顺序好像在哪里见过原创 2015-01-20 18:39:02 · 392 阅读 · 0 评论 -
复杂链表的复制
面试题26:复杂链表的复制题目:请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个pNext指针指向下一个结点外,还有一个pSibling指向链表中的任意一结点或者NULL。结点定义如下:struct ComplexNode{int value; ComplexNode*原创 2015-01-20 15:52:53 · 310 阅读 · 0 评论 -
丑数
面试题34:丑数 题目:我们把只包含因子2、3、5的数成为丑数。求按从小到大的顺序的第1500个丑数。习惯上把1当做第一个丑数分析:我的想法,先找到第一个丑数1,然后乘以2、3、5这样就可以得到下一批丑数,然后按照从小到大的顺序在对这批丑数乘以2、3、5.例如新得到的丑数为2、3、5,先选取最小的一个2,乘以2、3、5,得到的数字为4、6、10同理对3和5也这样操作得到的数为6、9、10和10、1原创 2015-02-09 16:57:30 · 272 阅读 · 0 评论 -
字符串的排列
面试题28:字符串的排列题目:输入一个字符串,打印出该字符串中字符的所有排列。分析:这个题目比较有意思,但是真要转换成代码还真是不好写。首先固定一个字符这是我的想法,然后把这个字符一次插入到第2.3.。。。n上,然后把第二个字符当成第一个,又是一个递归的做法。void Permutation(char* pStr){ if(pStr == NULL) { return ;原创 2015-01-21 19:06:12 · 262 阅读 · 0 评论 -
二进制中1的个数
面试题10:二级制中1的个数第一种解法:采用右移并且与1按位 与运算,若是1则结果1否则为0,这样便可以统计出二级制中的1的个数,代码如下:int count(int n){ int count = 0; while(n){ if(n>0){ count++; }原创 2015-01-04 21:04:45 · 284 阅读 · 0 评论 -
数值的整数次方
面试题11:数字的整数次方题目:实现函数dboule Power(double base,int exponent)。求base的exponent的次方看到题目之后第一反应有一道考查细节的题目,因为题目本身似乎太简单了,所以想到了关于次方的几种情况:base为0是无意义,exponent为0时都为0,为负数时相当于求base的-exponent次方的倒数。double Power(原创 2015-01-04 21:29:29 · 512 阅读 · 0 评论 -
打印从1到最大的n位数
面试题12:打印从1到最大的n位数题目:输入数字n,按顺序打印出从1到最大的n位十进制数,比如输入3则打印1-999.第一反应这个n的范围是多大,看来应该是足够大的一个数以至于int类型的数是绝对放不下的。因此这里考虑使用字符串的方式来存储这个大的数。n位数每一位上都是0-9,因此采用类型全排列的方式输出这个数也是比较好想到的。void Print1ToMaxOfNDi原创 2015-01-05 18:43:57 · 239 阅读 · 0 评论 -
在O(1)时间删除链表节点
面试题13:在O(1)时间删除链表节点题目:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。链表的结构如下:struct ListNode{int value; ListNode * next;}链表的删除相信大家都很熟悉,单链表的操作基本上都是from head to tail 的因为传统的删除节点需要知道它的前一原创 2015-01-05 19:39:10 · 333 阅读 · 0 评论 -
第一个只出现一次的字符
面试题35:第一个只出现一次的字符题目:在字符串中找出第一个只出现一次的字符。如输入“abaccdeff”,则输出'b'。解析:最好的办法是用一个哈希表来存储字符-出现次数,用字符作为key,出现次数最为value。这样查找的过程为O(1),所以这个思路的时间复杂度主要在构造这个哈希表。在c中char类型的数据为2^8=256个,因此数组的大小为256。需要遍历两次数组才可以完成这个功能,原创 2015-03-02 18:02:54 · 302 阅读 · 0 评论 -
栈的压入、弹出序列
面试题22:栈的压入、弹出序列题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。分析:考研的数据结构中也常有这种题目,解题的基本思路是:如果要得到第二序列中的第一元素需要将那么些元素入栈,然后出栈得到第一个元素,然后判断第二元素是不是在栈顶若不是继续入栈直到序列为空或者得到该元素。文字表达比较绕,画图表示:假设入栈序列为:1.2.3.4.5需原创 2015-01-15 14:35:13 · 234 阅读 · 0 评论 -
从尾到到打印链表
面试题5:从尾到头打印链表链表的Node的结构为:struct ListNode{ int Key; ListNode *Next;};看到题目时有两种想法,第一种是用栈,毕竟这就是先进后出的结构,完全满足题目要求。第二种方法就是链表的逆置。两种方法的时间复杂度都是O(n),都是遍历一遍链表然后输出,但是第二种方法改变了链表结构不可取。第一种方法的实现:vo原创 2014-12-10 10:08:16 · 264 阅读 · 0 评论 -
包含min函数的栈
面试题21:包含min函数的栈题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min.push及pop的时间复杂度为O(1)。分析:栈的pop()和push()操作都是O(1)的没什么问题,但是min函数在O(1)时间内实现就有问题了,若是在入栈时就进行排序,那么出栈的顺序就不在是先进后出,这样这个数据结构就不是栈了,所以肯定不能在原栈进行操作。原创 2015-01-14 15:14:00 · 321 阅读 · 0 评论 -
重建二叉树
我们知道根据二叉树的前序或者后序遍历的结果,加上中序遍历的结果便可以还原出这棵二叉树。原创 2014-12-16 17:00:09 · 244 阅读 · 0 评论 -
两个栈实现队列
面试题7:用两个栈实现队列 这个题目的思路比较清晰,栈的特点是先进后出,队列的特点是先进先出。用两个栈,先栈1入栈,出栈后栈2入栈,这里从栈2出栈的时候总体上就是先进先出了。import java.util.Stack ;public class Queue_stack{ Stack stack1 = new Stack(); Stack stack2 = new Sta原创 2014-12-17 10:25:06 · 274 阅读 · 0 评论 -
链表中倒数第k个节点
面试题15:链表中倒数第k个节点题目:输入一个链表,输出链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第一个结点。链表结点定义如下:struct ListNode{ int value; ListNode *next;}分析:看到这个题目莫名的熟悉,这是一道考研真题大概是2011年的。思路也比较清晰,使用两个指针,初原创 2015-01-09 09:13:27 · 344 阅读 · 0 评论 -
调整数组顺序是奇数位于偶数前面
面试题14:调整数组顺序使奇数位于偶数前面题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组前半部分,所有偶数位于后半部分。分析:第一反应想到了快速排序时的方法,从后往前找第一个奇数,从前往后找第一个偶数,找到后交换,直到两个指针相等。实现代码也和快速的代码很想。void ReorderOddEven(int *pData,int length)原创 2015-01-08 17:38:14 · 290 阅读 · 0 评论 -
数组中超过一半的数字
面试题:29数组中出现超过一半的数字题目:数组中有一个数字出现次数超过数组长度一半的数字,请找出这个数字。分析:首先题目给出了这个题目的假设条件,就是存在这样的一个数字。那么我的想法是先排序然后找第n/2数就是所要找的数字,排序里面速度最快的也就是快速排序,那么应用快速排序对数组进行排序然后再通过下标找到所要的结果。int MoreThanHalfNum (int*原创 2015-01-26 19:18:16 · 368 阅读 · 0 评论 -
从1到n整数中1出现的次数
面试题32:从1到n整数中1出现的次数题目:输入一个整数n,求1到n这n个整数的十进制表示中1出现的次数。分析:题目好绕口,其实就是求一个任意位数的整数中1出现的次数。这个题目好像在哪里见过。考虑到这个整数可能很大,采用计算的方法不合适或者说你直接能想到的办法就不要告诉面试官了,因为几乎不可能是对的。大神除外。我的想法是用一个字符数组来存储这个整数然后递归遍历整个数组的原创 2015-01-29 19:12:44 · 630 阅读 · 0 评论 -
反转链表
面试题:16反转链表题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点,链表结点定义如下:struct ListNode{ int value; ListNode * next;}分析:链表的逆置之所以时间复杂度比较高的原因还是在于单链表的操作必须要from head to tail,所以部能用普通的思路。只遍历一次链表在这过程原创 2015-01-09 19:50:45 · 332 阅读 · 0 评论 -
合并链表
面试题17:合并两个链表题目:输入两个递增排序的链表,合并这两个链表并使新的链表依然保持递增排序。链表结点定义如下:struct ListNode{int value;ListNode* next;}这个题目在考研里就有属于比较简单的一类,本来不打算写上来看到答案中采用的递归的写法,代码非常的整洁干净一时心动就写了上来。ListNode* Merge(ListNod原创 2015-01-12 15:04:53 · 451 阅读 · 0 评论 -
树的子结构
面试题:18题目:输入两棵二叉树A和B,判断B是不是A的子结构。二叉树结点的定义如下:struct BinaryTreeNode{int value;BinaryTreeNode* pLeft;BinaryTreeNode* pRight;}分析:首先我的想法,随意采用先序遍历方法遍历这两棵二叉树,如果B是A的子结构那么B的遍历序列肯定是A的序列的一个子序列。如原创 2015-01-13 09:17:38 · 289 阅读 · 0 评论 -
二维数组中的查找
题目:在一个二维数组中,每一行都按照从左到右,从上到下的顺序递增。请完成一个函数,输入这样的一个数组和一个整数,判断数组中是否含有该整数。假设数组为: 1 2 8 9原创 2014-12-08 20:18:35 · 301 阅读 · 0 评论 -
替换空格
题目:请实现一个函数,将字符串中的每个空格替换成%20,例如"we are happy"替换成"we%20are%20happy"看到这个题目第一反应是:是在原来字符串的基础上修改,还是在copy给另个字符串第一种:在原来的字符串上修改,这时候需要注意的问题是原来的字符的长度够不够的问题,如果不够这题目就没法做了,假设原来的字符串足够大。这时候想起了直接插入排序和简单选择排原创 2014-12-08 20:52:07 · 306 阅读 · 0 评论 -
顺时针打印矩阵
面试题20:顺时针打印矩阵题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如输入一个矩阵:12345678910111213141516则依次打印的数字为:1.2.3.4.8.12.16.15.14.13.9.5.6.7.11.10分析:这道题分析难原创 2015-01-14 10:37:34 · 282 阅读 · 0 评论 -
两个队列实现栈
两个栈实现队列比较好理解,这两个队列实现栈可就让我头疼了。因为怎么设计都是要先把一个队列的元素除最后一个元素全部出队,出队的元素全部放到另一个队列中,然后再把最后一个元素出队,这样就形成了“出栈”。需要两个队列,分别为q1和q2,则入栈直接为q1入队,出栈就想上面说的一样。具体的代码如下:void Push(Queue *q1, Queue *q2, int k){原创 2014-12-26 13:54:27 · 254 阅读 · 0 评论 -
二叉树的镜像
面试题:19二叉树的镜像题目:请完成一个函数,输入一个二叉树,该函数输出他的镜像。二叉树的结点定义如下:struct BinaryTreeNode{int value;BinaryTreeNode* Left;BinaryTreeNode* Right;};分析:所谓二叉树的镜像就是非叶结点的左右子树交换,但注意边界情况:输入的树为空。void MirrorRe原创 2015-01-14 10:02:19 · 294 阅读 · 0 评论 -
面试题36:数组中的逆序对
题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组的逆序对的总数。我的思路:实在是没想到什么好的办法,最古老的办法,从第一个元素开始逐一和后面的元素比较大小,如果符合逆序对的要求则count+1.时间复杂度为O(n^2),估计拿不到offer。正确的答案是采用归并排序的思想,将这个数组分割成小数组,先统计出数组内部原创 2015-03-05 17:56:57 · 331 阅读 · 0 评论