![](https://img-blog.csdnimg.cn/20201014180756780.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
剑指offer
文章平均质量分 57
瘦弱的皮卡丘
2018
展开
-
1~n 整数中 1 出现的次数
题目描述输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。示例 1:输入:n = 1输出:5 (分别是1 10 11 12)示例 2:输入:n = 13输出:6 (分别是1 10 11 12 13)思路首先我们知道,肯定可以用求模取余的方法来获取1~n这n个数每个数位上的数,如果是1的话则ans+1,但我们有更巧妙的方法。根据...原创 2022-01-18 18:07:41 · 2817 阅读 · 0 评论 -
不用加减乘除做加法。写一个函数,求两个整数之和,要求在函数体内不得使用“+”、“-”、“×”、“÷”四则运算符号。
面试题65:不用加减乘除做加法1.题目描述题目:写一个函数,求两个整数之和,要求在函数体内不得使用“+”、“-”、“×”、“÷”四则运算符号。2.题目分析首先我们可以分析5+17=22。实际上,我们可以分成三步进行:第一步只做各位相加不进位,此时相加的结果是12(个位数5和7相加不要进位是2,十位数0和1相加结果是1); 第二步做进位,5+7中有进位,进位的值是10; 第三步把前面两个结果加起来,12+10的结果是22,刚好5+17=22;接着我们就以二进制再来分析一下前面的“三步原创 2021-02-16 20:41:58 · 206 阅读 · 0 评论 -
求1+2+…+n,要求不能使用乘除法、for,while,if,else,switch,case等关键字及条件判断语句(A?B:C)
面试题64:求1+2+...+n1.题目描述题目:求1+2+…+n,要求不能使用乘除法、for,while,if,else,switch,case等关键字及条件判断语句(A?B:C)2.题目分析通常求1+2+...+n除了用公式n(n+1)/2,无外乎循环和递归两种思路。由于已经明确限制for和 while的使用,循环已经不能再用了。递归函数也需要用if语句或者条件判断语句来判断是继续递归下去还是终止递归,但现在题目已经不允许使用这两种语句了。解法一:利用构造函数求解循环只是让相同的原创 2021-02-16 20:00:04 · 1117 阅读 · 0 评论 -
什么是约瑟夫环
约瑟夫问题约瑟夫问题是个著名的问题:N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的胜利者。例如只有三个人,把他们叫做A、B、C,他们围成一圈,从A开始报数,假设报2的人被杀掉。首先A开始报数,他报1。侥幸逃过一劫。 然后轮到B报数,他报2。非常惨,他被杀了 C接着从1开始报数 接着轮到A报数,他报2。也被杀死了。 最终胜利者是C约瑟夫环是一个经典的数学问题,我们不难发现这样的依次报数,似乎有规律可循。为了方便导出递.原创 2021-02-16 14:42:10 · 5104 阅读 · 1 评论 -
股票的最大利润。假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?
面试题63:股票的最大利润1.题目描述题目:假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?例如,一只股票在某些时间节点的价格为{9,11,8,5,7,12,16,14}。如果我们能在价格为5的时候买入并在价格为16时卖出,则能收获最大的利润11。2.题目分析我们先定义函数dIff(i)为当卖出价为数组中第i个数字时可能获得的最大利润。显然,在卖出价固定时,买入价越低获得的利润越大。也就是说,如果在扫描到数组中的第i个数字时,只要我们能够记原创 2021-02-16 14:27:52 · 1249 阅读 · 0 评论 -
扑克牌中的顺子。从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成任意数字。
面试题36:扑克牌中的顺子1.题目描述题目:从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成任意数字。2.题目分析我们需要把扑克牌的背景抽象成计算机语言。不难想象,我们可以把5张牌看成由5个数字组成的数组。大、小王是特殊的数字,我们不妨把它们都定义为0,这样就能和其他扑克牌区分开来了,接下来我们分析怎样判断5个数字是不是连续的,最直观的方法是把数组排序。值得注意的是,由于0可以当成任意数字,我们可原创 2021-02-16 12:38:33 · 1717 阅读 · 0 评论 -
字符串中第一个只出现一次的字符。在字符串中找出第一个只出现一次的字符。
面试题35:第一个只出现一次的字符1.题目描述题目:字符串中第一个只出现一次的字符。在字符串中找出第一个只出现一次的字符。例如,如输入"abaccdeff",则输出b。2.题目分析由于题目与字符出现的次数相关,那么我们是不是可以统计每个字符在该字符串中出现的次数?要达到这个目的,我们需要一个数据容器来存放每个字符的出现次数。在这个数据容器中,可以根据字符来查找它出现的次数,也就是说这个容器的作用是把一个字符映射成一个数字。在常用的数据容器中,哈希表正是这个用途。为了解决这个问题,我原创 2021-02-15 23:12:59 · 476 阅读 · 0 评论 -
丑数 | 我们把只包含因子2、3和5的数称作丑数。求按从小到大的顺序的第1500个丑数。
面试题34:丑数1.题目描述我们把只包含因子2、3和5的数称作丑数。求按从小到大的顺序的第1500个丑数。例如6(6=3*2)、8(8=2*4,4=2*2)都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做第一个丑数。2.题目分析根据丑数的定义,丑数应该是另一个丑数乘以2、3或者5的结果(1除外)。因此我们可以创建一个数组,里面的数字是排好序的丑数,每一个丑数都是前面的丑数...原创 2020-05-06 19:04:44 · 1132 阅读 · 0 评论 -
把数组排成最小的数 | 输入一个正整数数组,把数组里所有数字拼接起来排成一个数打印能拼接出的所有数字中最小的一个。
面试题33:把数组排成最小的数1.题目描述题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这3个数字能排成的最小数字321323。2.题目分析要确定排序规则,就要比较两个数字,也就是给出两个数字m和n,我们需要确定一个规则判断m和n哪个应该排在前面,而不是仅仅比较这两个数字的值哪个更大...原创 2020-05-06 15:32:55 · 707 阅读 · 0 评论 -
连续子数组的最大和 | 求所有子数组的和的最大值
面试题31:连续子数组的最大和1.题目描述输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。例如输入的数组为{1,-2,3,10,-4,7,2,-5}和最大的子数组为{3,10,-4,7,2},因此输出为该子数组的和18。看到这道题,很多人都能想到最直观的方法,即枚举出数组的所有子数组并求出它们...原创 2020-05-02 20:25:53 · 420 阅读 · 1 评论 -
查找数组中最小的k个数 | 最小的k个数
面试题30:最小的k个数1.题目描述输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2,7、3、8这8个数字,则最小的4个数字是1、2、3、4。2.题目分析解法一:O(n)的算法,只有当我们可以修改输入的数组时可用从解决面试题29“数组中出现次数超过一半的数字”得到了启发,我们同样可以基于 Partition函数来解决这个问题。如果基于数组的第k个数字来调整,使得比...原创 2020-05-02 19:55:54 · 1582 阅读 · 0 评论 -
查找数组中出现次数超过一半的数字
面试题29:数组中出现次数超过一半的数字1.题目描述数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。2.题目分析解法1:基于 Partition函数的O(n)算法数组中有一个数字出现的次数超过了数组长度的一半。如果把这个数组排序,那么排序...原创 2020-04-29 14:24:43 · 981 阅读 · 0 评论 -
二叉搜索树与双向链表 | 将一个二又搜索树转换成一个排序的双向链表
面试题27:二叉搜索树与双向链表1.题目描述输入一棵二叉搜索树,将该二又搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。比如输入下图中左边的二又搜索树,则输出转换之后的排序双向链表。二叉树结点的定义如下: struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft...原创 2020-04-28 16:33:30 · 188 阅读 · 0 评论 -
复杂链表的复制 | 赋值链表
面试题26:复杂链表的复制1.题目描述请实现函数 ComplexListNode*Clone(ComplexListNode* pHead)复制一个复杂链表。在复杂链表中,每个结点除了有一个 m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任意结点或者NULL。结点的C++定义如下:struct ComplexListNode{ int m_nV...原创 2020-04-27 21:14:18 · 366 阅读 · 0 评论 -
二叉树中和为某一值的路径
面试题25:二叉树中和为某一值的路径1.题目描述输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。二又树结点的定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_...原创 2020-04-27 19:59:11 · 251 阅读 · 0 评论 -
二叉搜索树的后序遍历序列
面试题24:二叉搜索树的后序遍历序列1.题目描述输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回tue,否则返回flse。假设输入的数组的任意两个数字都互不相同。例如输入数组{5,7,6,9,11,10,8},则返回tue,因为这个整数序列是下图二叉搜索树的后序遍历结果。如果输入的数组是{7,4,6,5},由于没有哪棵二叉搜索树的后序遍历的结果是这个序列,...原创 2020-04-27 18:43:44 · 235 阅读 · 0 评论 -
从上往下打印二叉树 | 层次遍历二叉树
面试题23:从上往下打印二叉树题目描述:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。例如输入下图中的二叉树,则依次打印出8、6、10、5、7、9、11。叉树结点的定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* ...原创 2020-04-27 17:34:00 · 272 阅读 · 0 评论 -
二叉树的镜像
面试题19:二叉树的镜像1.题目描述题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。二叉树结点的定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;};2.题目分析为了能够形成直观的印象,我们可以自己画一棵二...原创 2020-04-26 23:06:19 · 218 阅读 · 1 评论 -
树的子结构 | 输入两棵二叉树A和B,判断B是不是A的子结构
面试题18:树的子结构1.题目描述输入两棵二叉树A和B,判断B是不是A的子结构。二叉树结点的定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRirht;];2.题目分析例如下图中的两棵二叉树,由于A中有一部分子树的结构和B是一...原创 2020-04-26 22:40:03 · 610 阅读 · 1 评论 -
用两个栈实现队列
面试题7:用两个栈实现队列1.题目描述用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。template<typename T>class CQueue{ public: CQueue(void); ~CQueue(vo...原创 2020-04-26 15:29:04 · 172 阅读 · 0 评论 -
重建二又树 | 根据先序遍历和中序遍历建立二叉树
面试题6:重建二又树1.题目描述输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。二叉树结点的定义如下:typedef struct BtNode{ struct BtNode* leftchild; struct BtNode* rightchild; ElemType data;}BtNode,*Binary...原创 2020-04-21 15:15:52 · 364 阅读 · 0 评论 -
从尾到头打印链表 | 逆序打印链表
面试题5:从尾到头打印链表1.题目描述题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值,链表结点定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};2.分析问题通常打印是一个只读操作,我们不希望打印时修改内容。假设面试官也要求这个题目不能改变链表的结构。接下来我们想到解决这个问题肯定要遍历链...原创 2020-04-21 14:02:14 · 296 阅读 · 0 评论 -
字符串的排列
面试题28:字符串的排列一.题目描述输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。二.分析问题 1.举例分析我们可以考虑把这个复杂的问题分解成小的问题。比如,我们把一个字符串看成由两部分组成:第一部分为它的第一个字符,第二部分是后面的所有字符。我们...原创 2019-11-25 20:09:30 · 211 阅读 · 0 评论 -
栈的压入、弹出序列
面试题22:栈的压入、弹出序列一.题目描述输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1、2、3、4、5是某栈的压栈序列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列,但4、3、5、1、2就不可能是该压栈序列的弹出序列。二.问题分析1.举例分析以弹出序列4、5、3、2、1为例分析压栈和...原创 2019-11-25 17:21:33 · 480 阅读 · 0 评论 -
包含min函数的栈
面试题21:包含min函数的栈一.题目描述定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push及pop的时间复杂度都是O(1)。二.分析问题1.解题思路我们首先想到在栈里添加一个成员变量存放最小的元素。每次压入一个新元素进栈的时候,如果该元素比当前最小的元素还要小,则更新最小元素。但如果当前最小的元素被弹出栈了,如何得到下一个最...原创 2019-11-24 14:08:13 · 97 阅读 · 0 评论 -
顺时针打印矩阵
面试题20:顺时针打印矩阵一.题目描述输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如:如果输入如下矩阵:则依次打印出数字1、2、3、4、8、12、16、15、14、13、9、5、6、7、11、10。二.分析问题1.解题思路由于是以从外圈到内圈的顺序依次打印,我们可以把矩阵想象成若干个圈,如图所示。以用一个循环来打印矩阵,每一次打印矩阵中的一个...原创 2019-11-24 13:19:53 · 160 阅读 · 0 评论 -
合并两个排序的链表
面试题17:合并两个排序的链表一.题目描述输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。例如输入图3.7中的链表1和链表2,则合并之后的升序链表如链表3所示。链表结点定义如下:struct ListNode{ int m_nValue; ListNode* m_pNext;};二.分析问题1.举例分析注:链表...原创 2019-11-16 16:08:11 · 212 阅读 · 0 评论 -
反转链表 | 单链表的逆置
面试题16:反转链表一.题目描述定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。链表结点定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};二.分析问题1.举例分析2.解题思路解法1为了正确地反转一个链表,需要调整链表中指针的方向。为了将调整指针这个复杂的过...原创 2019-11-16 13:50:54 · 451 阅读 · 0 评论 -
链表中倒数第k个结点
面试题15:链表中倒数第k个结点一.题目描述输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。链表结点定义如下:struct ListNode{ int m_nValue; ListN...原创 2019-11-15 21:20:27 · 176 阅读 · 0 评论 -
调整数组顺序使奇数位于偶数前面
面试题14:调整数组顺序使奇数位于偶数前面一.题目描述输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。二.分析问题解法1这个题目要求把奇数放在数组的前半部分,偶数放在数组的后半部分,因此所有的奇数应该位于偶数的前面。也就是说我们在扫描这个数组的时候,如果发现有偶数出现在奇数的前面,我们可以交换它们的顺序,交换之...原创 2019-11-15 21:01:05 · 248 阅读 · 0 评论 -
在O(1)时间删除链表结点
面试题13:在O(1)时间删除链表结点一.题目描述给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。链表结点与函数的定义如下:struct ListNode{ int m_nValue; ListNode* m_pNext;};void DeleteNode(ListNode** pListHead,ListNode* pToBeDel...原创 2019-11-15 18:38:30 · 193 阅读 · 0 评论 -
打印1到最大的n位数
面试题12:打印1到最大的n位数一.题目描述输入数字n,按顺序打印出1到最大的n位十进制数。比如输入3,则打印出1,2,3一直到最大的3位数即999。二.分析问题1.解题思路解法1因为考虑到若果输入的n灯值可能会很大,用int型和long long型都会溢出,所以我们利用字符串和数组来表达大数。我在这里选择用字符串来解决问题。用字符串表示数字的时候,我们让字符串的每一个字符...原创 2019-11-15 17:21:14 · 238 阅读 · 0 评论 -
数值的整数次方
面试题11:数值的整数次方一.题目描述实现函数double Power(double base,int exponent),求base得exponent次方。不得使用库函数,同时不需要考虑大数问题。二.分析问题1.解题思路解法1这道题因为不用考虑大数的问题,所以比较简单,但是我们不能因此掉以轻心,要将所有可能出现的情况考虑清楚。如果指数为负数的时候,我们先对指数求绝对值...原创 2019-11-13 16:06:50 · 298 阅读 · 0 评论 -
二进制中1的个数
面试题10:二进制中1的个数一:题目描述请实现一个函数,输入一个整数,输出该二进制表示中1的个数。例如把9表示成二进制时1001,有两位是1。因此如果输入9,该函数输出2。二:分析问题解法1首先假设要判断的数字为n,首先把n和1做与运算,判断n的最低为是不是1。接着把1左移一位,再和n做与运算,就能判断n的次低位是不是1......这样反复左移,每次都能判断i的其中一位是不是1...原创 2019-11-11 19:58:03 · 264 阅读 · 0 评论 -
旋转数组的最小数字
面试题8:旋转数组的最小数字一.题目描述把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。二.分析问题1.举例分析以前面的数组{3,4,5,1,2}为例,我们先把第一个指针指向第0个元素,把第二个指针指向最后一个元素。...原创 2019-11-11 18:48:03 · 113 阅读 · 0 评论 -
替换空格
面试题4:替换空格一.题目描述请实现一个函数,把字符串中的每个空格替换为"%20"。例如输入"We are happy.",则输出"We%20are%20happy."。(输入的字符串后面有足够多的空余内存)二.分析问题1.举例分析(以上述题目中的例子为例)"We are happy."这个字符串的长度是14(包括结尾的'\0'),里面有两个空格,因此替换之后字符串的长度为...原创 2019-11-10 23:37:55 · 119 阅读 · 0 评论 -
二维数组中的查找
面试题3:二维数组中的查找一:题目描述在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。例如下面的二位数组,若查找数字7,则返回true;如果查找数字5,则返回false二:分析问题1.举例分析假设我们现在要查找的数字是7。首先我们我们选取数组右上...原创 2019-11-06 22:37:02 · 892 阅读 · 0 评论 -
指针和数组的区别
在C和C++中,数组和指针是相互关联又有区别的两个概念。当我们声明一个数组时,其数组的名字也是一个指针,该指针指向这个数组的首地址,因此我们可以用一个指针来访问数组。下面,我们来看一段代码,来了解数组和指针的区别:#include <stdio.h>int GetSize(int data[]){ return sizeof(data);}int main(){...原创 2019-11-06 19:43:19 · 111 阅读 · 0 评论