剑指offer题解
《剑指Offer》第二版的题目,共76道题目,每道题都有详细的题解分析。
林小鹿@
后端开发,热衷于算法,每日更新高质量算法题解。
展开
-
《剑指offer刷题笔记》33、之字形打印二叉树【c++详细题解】
题目请实现一个函数按照之字形顺序从上向下打印二叉树。即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。样例输入如下图所示二叉树[8, 12, 2, null, null, 6, 4, null, null, null, null] 8 / \ 12 2 / \ 6 4输出:[[8], [2, 12], [6, 4]]思路在上一题的基础上加一个标记,奇数行为从左到右,偶数行为从右到左。代码原创 2021-05-04 22:00:55 · 2701 阅读 · 1 评论 -
《剑指offer刷题笔记》32、分行从上往下打印二叉树【c++详细题解】
题目从上到下按层打印二叉树,同一层的结点按从左到右的顺序打印,每一层打印到一行。样例输入如下图所示二叉树[8, 12, 2, null, null, 6, null, 4, null, null, null] 8 / \ 12 2 / 6 / 4输出:[[8], [12, 2], [6], [4]]思路1(BFS)O(n)O(n)O(n)宽度优先遍历,一层一层来做。即:将根节点插入队列中;创建一个新队列,用来按顺序保存下一层的所有子节点原创 2021-05-04 21:57:53 · 186 阅读 · 1 评论 -
《剑指offer刷题笔记》31、不分行从上往下打印二叉树【c++详细题解】
题目从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。样例输入如下图所示二叉树[8, 12, 2, null, null, 6, null, 4, null, null, null] 8 / \ 12 2 / 6 / 4输出:[8, 12, 2, 6, 4]思路(BFS) O(n)O(n)O(n)我们从根节点开始按宽度优先的顺序遍历整棵树,每次先扩展左儿子,再扩展右儿子。这样我们会:先扩展根节点;再依次扩展根节点的左原创 2021-05-04 21:54:41 · 165 阅读 · 0 评论 -
《剑指offer刷题笔记》30、栈的压入、弹出序列【c++详细题解】
题目输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列 1,2,3,4,5 是某栈的压入顺序,序列 4,5,3,2,1是该压栈序列对应的一个弹出序列,但 4,3,5,1,2就不可能是该压栈序列的弹出序列。注意:若两个序列长度不等则视为并不是一个栈的压入、弹出序列。若两个序列都为空,则视为是一个栈的压入、弹出序列。样例输入:[1,2,3,4,5] [4,5,3,2,1]输出:true思路(模拟 )O(原创 2021-04-28 22:28:22 · 215 阅读 · 0 评论 -
《剑指offer刷题笔记》28、顺时针打印矩阵【c++详细题解】
题目输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。输入:[ [1, 2, 3, 4], [5, 6, 7, 8], [9,10,11,12]]输出:[1,2,3,4,8,12,11,10,9,5,6,7]思路(模拟) O(n2)O(n2)O(n2)我们顺时针定义四个方向:上右下左。从左上角开始遍历,先往右走,走到不能走为止,然后更改到下个方向,再走到不能走为止,依次类推,遍历 n2n2n2 个格子后停止。时间复杂度矩阵中每个格子遍历一次,所以总时间复杂度原创 2021-04-28 22:24:28 · 182 阅读 · 0 评论 -
《剑指offer刷题笔记》27、对称的二叉树【c++详细题解】
题目请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。样例如下图所示二叉树[1,2,2,3,4,4,3,null,null,null,null,null,null,null,null]为对称二叉树: 1 / \ 2 2 / \ / \3 4 4 3如下图所示二叉树[1,2,2,null,4,4,3,null,null,null,null,null,null]不是对称二叉树: 1 / \ 2 2原创 2021-04-28 22:22:39 · 174 阅读 · 0 评论 -
《剑指offer刷题笔记》26、二叉树的镜像【c++详细题解】
题目输入一个二叉树,将它变换为它的镜像。样例输入树: 8 / \ 6 10 / \ / \ 5 7 9 11 [8,6,10,5,7,9,11,null,null,null,null,null,null,null,null] 输出树: 8 / \ 10 6 / \ / \ 11 9 7 5 [8,10,6,11,9,7,5,null,null,null,null,null,null,null,null]原创 2021-04-28 22:21:25 · 168 阅读 · 0 评论 -
《剑指offer刷题笔记》25、树的子结构【c++详细题解】
题目输入两棵二叉树 A,B,判断 B 是不是 A 的子结构。我们规定空树不是任何树的子结构。样例树 A: 8 / \ 8 7 / \ 9 2 / \ 4 7树 B: 8 / \ 9 2返回 true,因为 B 是 A 的子结构。思路(二叉树,递归) O(nm)O(nm)O(nm)代码分为两个部分:遍历树A中的所有非空节点R;判断树A中以R为根节点的子树是不是包含和树B一样的结构,且我们从根节点开始匹配;对原创 2021-04-28 22:19:26 · 156 阅读 · 0 评论 -
《剑指offer刷题笔记》24、合并两个排序的链表【c++详细题解】
题目输入两棵二叉树 A,B,判断 B 是不是 A 的子结构。我们规定空树不是任何树的子结构。样例树 A: 8 / \ 8 7 / \ 9 2 / \ 4 7树 B: 8 / \ 9 2返回 true,因为 B 是 A 的子结构。思路(二叉树,递归) O(nm)O(nm)O(nm)代码分为两个部分:遍历树A中的所有非空节点R;判断树A中以R为根节点的子树是不是包含和树B一样的结构,且我们从根节点开始匹配;对原创 2021-04-28 22:17:01 · 161 阅读 · 0 评论 -
《剑指offer刷题笔记》23、反转链表【c++详细题解】
题目定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。思考题:请同时实现迭代版本和递归版本。样例输入:1->2->3->4->5->NULL输出:5->4->3->2->1->NULL思路1(链表操作,迭代) (n)(n)(n)翻转即将所有节点的next指针指向前驱节点。由于是单链表,我们在迭代时不能直接找到前驱节点,所以我们需要一个额外的指针保存前驱节点。同时在改变当前节点的next指针前,不要忘原创 2021-04-26 19:11:25 · 2754 阅读 · 0 评论 -
《剑指offer刷题笔记》22、链表中环的入口结点 【c++详细题解】
题目给定一个链表,若其中包含环,则输出环的入口节点。若其中不包含环,则输出null。样例给定如上所示的链表:[1, 2, 3, 4, 5, 6]2注意,这里的2表示编号是2的节点,节点编号从0开始。所以编号是2的节点就是val等于3的节点。则输出环的入口节点3.思路(链表,快慢指针扫描)O(n)O(n)O(n)本题的做法比较巧妙。用两个指针 first,secondfirst,secondfirst,second分别从起点开始走,firstfirstfirst每次走一步,sec原创 2021-04-26 19:09:25 · 239 阅读 · 0 评论 -
《剑指offer刷题笔记》21、链表中倒数第k个节点 【c++详细题解】
题目输入一个链表,输出该链表中倒数第 kkk个结点。注意:k >= 1;如果 kkk 大于链表长度,则返回$ NULL$;样例输入:链表:1->2->3->4->5 ,k=2输出:4思路(链表)O(n)O(n)O(n)由于单链表不能索引到前驱节点,所以只能从前往后遍历。我们一共遍历两次:第一次遍历得到链表总长度 nnn;链表的倒数第 kkk 个节点,相当于正数第n−k+1n−k+1n−k+1 个节点。所以第二次遍历到第$ n−k+1$ 个节点,原创 2021-04-26 19:06:15 · 2686 阅读 · 0 评论 -
《剑指offer刷题笔记》20、调整数组顺序使奇数位于偶数前面 【c++详细题解】
题目输入一个整数数组,实现一个函数来调整该数组中数字的顺序。使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分。样例输入:[1,2,3,4,5]输出: [1,3,5,2,4]思路1(枚举) O(n)O(n)O(n)定义两个数组,分别记录数组中的奇数和偶数。时间复杂度分析枚举整个数组,判断每个数是否是奇数或者偶数的时间复杂度为O(n)O(n)O(n)。由于多开了两个数组,这样的做法空间复杂度会变高。代码1class Solution {public: void原创 2021-04-24 20:14:33 · 2677 阅读 · 0 评论 -
《剑指offer刷题笔记》19、表示数值的字符串 【c++详细题解】
题目请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。注意:小数可以没有整数部分,例如.123等于0.123;小数点后面可以没有数字,例如233.等于233.0;小数点前面和后面可以有数字,例如233.666;当e或E前面没有数字时,整个字符串不能表示数字,例如.e1、e1;当e或E后面没有整数原创 2021-04-24 20:12:18 · 168 阅读 · 0 评论 -
《剑指offer刷题笔记》18、正则表达式匹配【c++详细题解】
请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配。样例输入:s="aa"p="a*"输出:true思路(动态规划)O(nm)O(nm)O(nm)状态表示:f[i][j]表示p从j开始到结尾,是否能匹配s从i开始到结尾状态转移:如果p[原创 2021-04-24 20:10:06 · 2734 阅读 · 0 评论 -
《剑指offer刷题笔记》36、复杂链表的复刻 【c++详细题解】
题目请实现一个函数可以复制一个复杂链表。在复杂链表中,每个结点除了有一个指针指向下一个结点外,还有一个额外的指针指向链表中的任意结点或者null。注意:函数结束后原链表要与输入时保持一致。思路原链表图形: 虚线为random指针1、在每个节点的后面加上它的复刻,将原链表和复刻链表连在一起。2、从前往后遍历每一个原链表节点,对于有random指针的节点p,我们让它的p->next->random = p->random->next,这样我们就完成了对原链表ran原创 2021-04-13 22:24:14 · 170 阅读 · 0 评论 -
《剑指offer刷题笔记》17、删除链表中重复的节点 【c++详细题解】
题目在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留。样例1输入:1->2->3->3->4->4->5输出:1->2->5样例2输入:1->1->1->2->3输出:2->3思路(线性扫描)O(n)O(n)O(n)为了方便处理边界情况,我们定义一个虚拟元素$dummy $指向链表头节点。然后从前往后扫描整个链表,每次扫描元素相同的一段,如果这段中的元素个数多于111个原创 2021-04-11 21:57:16 · 2657 阅读 · 0 评论 -
《剑指offer刷题笔记》16、在O(1)时间删除链表结点 【c++详细题解】
题目给定单向链表的一个节点指针,定义一个函数在O(1)O(1)O(1)时间删除该结点。假设链表一定存在,并且该节点一定不是尾节点。样例输入:链表 1->4->6->8 删掉节点:第2个节点即6(头节点为第0个节点)输出:新链表 1->4->8思路(链表) O(1)O(1)O(1)由于是单链表,我们不能找到前驱节点,所以我们不能按常规方法将该节点删除。我们可以换一种思路,将下一个节点的值复制到当前节点,然后将下一个节点删除即可。时间复杂度只原创 2021-04-11 21:54:40 · 177 阅读 · 0 评论 -
《剑指offer刷题笔记》15、数值的整数次方 【c++详细题解】
题目实现函数double Power(double base, int exponent),求base的 exponent次方。不得使用库函数,同时不需要考虑大数问题。只要输出结果与答案的绝对误差不超过 $10^−2 $即视为正确。注意:不会出现底数和指数同为0的情况当底数为0时,指数一定为正样例1输入:10 ,2输出:100样例2输入:10 ,-2 输出:0.01思路(模拟) O(logn)O(logn)O(logn)由于本题的指数是int范围,可能很大,所以原创 2021-04-11 21:52:28 · 179 阅读 · 0 评论 -
《剑指offer刷题笔记》14、二进制中1的个数 【c++详细题解】
题目输入一个 323232 位整数,输出该数二进制表示中 111 的个数。注意:负数在计算机中用其绝对值的补码来表示。样例1输入:9输出:2解释:9的二进制表示是1001,一共有2个1。样例2输入:-2输出:31解释:-2在计算机里会被表示成11111111111111111111111111111110, 一共有31个1。思路1lowbit(x)lowbit(x)lowbit(x)函数的作用lowbit(x)lowbit(x)lowbit(x)操作返回 xx原创 2021-04-06 19:40:09 · 2756 阅读 · 0 评论 -
《剑指offer刷题笔记》13、剪绳子【c++详细题解】
题目给你一根长度为 nnn绳子,请把绳子剪成mmm段(mmm、nnn 都是整数,2≤n≤582≤n≤582≤n≤58 并且 m≥2m≥2m≥2)。每段的绳子的长度记为k[1]、k[2]、……、k[m]k[1]、k[2]、……、k[m]k[1]、k[2]、……、k[m]。k[1]k[2]…k[m]k[1]k[2]…k[m]k[1]k[2]…k[m]可能的最大乘积是多少?例如当绳子的长度是 888时,我们把它剪成长度分别为222、333、333、 的三段,此时得到最大的乘积181818。样例输入:8原创 2021-04-06 19:37:16 · 251 阅读 · 0 评论 -
《剑指offer刷题笔记》12、机器人的运动范围 【c++详细题解】
题目地上有一个 mmm 行和 nnn 列的方格,横纵坐标范围分别是 0∼m−10∼m−10∼m−1 和0∼n−10∼n−10∼n−1。一个机器人从坐标 (0,0)(0,0)(0,0) 的格子开始移动,每一次只能向左,右,上,下四个方向移动一格。但是不能进入行坐标和列坐标的数位之和大于 kkk 的格子。请问该机器人能够达到多少个格子?样例1输入:k=7, m=4, n=5输出:20样例2输入:k=18, m=40, n=40输出:1484解释:当k为18时,机器人能够进入方格(3原创 2021-04-06 19:33:37 · 227 阅读 · 0 评论 -
《剑指offer刷题笔记》11、矩阵中的路径【c++详细题解】
题目请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。注意:输入的路径不为空;所有出现的字符均为大写英文字母;样例matrix=[ ["A","B","C","E"], ["S","F","C","S"], ["A","D","E","E"]]str="BCCE" , return "tr原创 2021-04-06 19:28:39 · 207 阅读 · 0 评论 -
《剑指offer刷题笔记》6、重建二叉树 【c++详细题解】
题目输入一棵二叉树前序遍历和中序遍历的结果,请重建该二叉树。注意:二叉树中每个节点的值都互不相同;输入的前序遍历和中序遍历一定合法;样例给定:前序遍历是:[3, 9, 20, 15, 7]中序遍历是:[9, 3, 15, 20, 7]返回:[3, 9, 20, null, null, 15, 7, null, null, null, null]返回的二叉树如下所示: 3 / \ 9 20 / \ 15 7思路(递归)O(n)O(n)O(原创 2021-04-05 13:34:27 · 2092 阅读 · 6 评论 -
《剑指offer刷题笔记》5、从尾到头打印链表 【c++详细题解】
题目输入一个链表的头结点,按照 从尾到头 的顺序返回节点的值。返回的结果用数组存储。样例输入:[2, 3, 5]返回:[5, 3, 2]思路(遍历链表) O(n)O(n)O(n)单链表只能从前往后遍历,不能从后往前遍历。因此我们先从前往后遍历一遍输入的链表,将结果记录在答案数组中。最后再将得到的数组逆序即可。时间复杂度分析链表和答案数组仅被遍历了常数次,所以总时间复杂度是 O(n)O(n)O(n)。代码class Solution {public: vector<原创 2021-04-05 13:31:39 · 211 阅读 · 0 评论 -
《剑指offer刷题笔记》 2、不修改数组找出重复的数字 【c++详细题解】
题目给定一个长度为 n+1n+1n+1 的数组nums,数组中所有的数均在 1∼n1∼n1∼n 的范围内,其中 n≥1n≥1n≥1。请找出数组中任意一个重复的数,但不能修改输入的数组。样例给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。返回 2 或 3。思考题:如果只能使用 O(1)O(1)O(1)的额外空间,该怎么做呢?思路(分治,抽屉原理) O(nlogn)O(nlogn)O(nlogn)这道题目主要应用了抽屉原理和分治的思想。抽屉原理:n+1 个苹果放在原创 2021-04-01 21:41:49 · 259 阅读 · 0 评论 -
《剑指offer刷题笔记》10、 旋转数组的最小数字 【c++详细题解】
题目把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个升序的数组的一个旋转,输出旋转数组的最小元素。例如数组 3,4,5,1,2{3,4,5,1,2}3,4,5,1,2为 1,2,3,4,5{1,2,3,4,5}1,2,3,4,5 的一个旋转,该数组的最小值为 111。数组可能包含重复项。注意:数组内所含元素非负,若数组大小为 000,请返回 −1−1−1。样例输入:nums=[2,2,2,0,1]输出:0思路1(遍历)O(n)O(n)O(n)原来的数组是一原创 2021-04-05 13:47:27 · 199 阅读 · 0 评论 -
《剑指offer刷题笔记》9、斐波那契数列 【c++详细题解】
题目输入一个整数 n ,求斐波那契数列的第 n 项。假定从 0 开始,第 0 项为 0。(n≤39)(n≤39)(n≤39)样例输入整数 n=5 返回 5思路1递推O(n)O(n)O(n)递推公式 : f[i] = f[i-1] + f[i-2];代码1class Solution {public: int Fibonacci(int n) { int f[10010]; f[0] = 0; f[1] = 1;原创 2021-04-05 13:42:43 · 203 阅读 · 0 评论 -
《剑指offer刷题笔记》7、二叉树的下一个节点 【c++详细题解】
题目给定一棵二叉树的其中一个节点,请找出中序遍历序列的下一个节点。注意:如果给定的节点是中序遍历序列的最后一个,则返回空节点;二叉树一定不为空,且给定的节点一定不是空节点;样例假定二叉树是:[2, 1, 3, null, null, null, null], 给出的是值等于2的节点。则应返回值等于3的节点。解释:该二叉树的结构如下,2的后继节点是3。 2 / \1 3思路(模拟) O(h)O(h)O(h)这道题目就是让我们求二叉树中给定节点的后继。分情况讨论即可原创 2021-04-05 13:38:37 · 178 阅读 · 0 评论 -
《剑指offer刷题笔记》4、替换空格 【c++详细题解】
题目请实现一个函数,把字符串中的每个空格替换成"%20"。你可以假定输入字符串的长度最大是 1000。注意输出字符串的长度可能大于 1000。样例输入:"We are happy."输出:"We%20are%20happy."思路1(线性扫描) O(n)O(n)O(n)这个题在C++里比较好做,我们可以从前往后枚举原字符串:如果遇到空格,则在string类型的答案中添加 "%20";如果遇到其他字符,则直接将它添加在答案中;但在C语言中,我们没有string这种好用的模板,需要自原创 2021-04-05 13:27:38 · 219 阅读 · 0 评论 -
《剑指offer刷题笔记》3、二维数组中的查找 【c++详细题解】
题目在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。样例输入数组:[ [1,2,8,9], [2,4,9,12], [4,7,10,13], [6,8,11,15]]如果输入查找数值为7,则返回true,如果输入查找数值为5,则返回false。最简单的思路是遍历二维数组,然后查找该数,但这样做的时间复杂度是O(n∗m)O(n*m)O(n∗m)。因此我原创 2021-04-01 21:48:35 · 254 阅读 · 0 评论 -
《剑指offer刷题笔记》 1、找出数组中重复的数字 【c++详细题解】
题目:给定一个长度为 n的整数数组 nums,数组中所有的数字都在0∼n−1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。注意:如果某些数字不在 0∼n−1 的范围内,或数组中不包含重复数字,则返回 -1;样例:给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。返回 2 或 3。思路1:时间复杂度O(n)O(n)O(n)使用unordered_set代码1:class Solution原创 2021-04-01 21:32:44 · 335 阅读 · 0 评论