
剑指 Offer(第 2 版)
文章平均质量分 91
面试必备
优惠券已抵扣
余额抵扣
还需支付
¥9.90
¥99.00
购买须知?
本专栏为图文内容,最终完结不会低于15篇文章。
订阅专栏,享有专栏所有文章阅读权限。
本专栏为虚拟商品,基于网络商品和虚拟商品的性质和特征,专栏一经购买无正当理由不予退款,不支持升级,敬请谅解。
某某的好奇心
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
3.数组中重复的数字
对于遍历到的每个元素,判断哈希表中是否存在该元素,如果哈希表中存在该元素,即找到了一个重复的数字,返回该数字即可;数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。进行排序,然后遍历排序后的数组,判断相邻的两个元素是否相等,如果相等,即找到了一个重复的数字,返回该数字即可。3) 交换过程中,如存在重复元素,v=nums[v],这里的v为交换更新后的。相等,即找到了一个重复的数字,返回该数字即可;,如果是,则继续遍历下一个元素;不相等,继续遍历,直到找到一个重复的数字。原创 2024-07-22 17:19:59 · 886 阅读 · 0 评论 -
4. 二维数组中的查找
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。这里我们以左下角作为起始搜索点,往右上方向开始搜索,比较当前元素。如果所有行都搜索完了,都没有找到目标值,说明目标值不存在,返回。由于每一行的所有元素升序排列,因此,,说明找到了目标值,直接返回。,说明这一行的所有元素都小于。分别为矩阵的行数和列数。分别为矩阵的行数和列数。给定 target =,应该继续搜索下一行。原创 2024-07-24 13:54:38 · 690 阅读 · 0 评论 -
5. 替换空格
我们直接遍历字符串,遇到空格就替换成。中的每个空格替换成"%20"。请实现一个函数,把字符串。原创 2024-07-24 15:15:09 · 692 阅读 · 0 评论 -
6. 从尾到头打印链表无标题
通过这个例子,可以清楚地看到递归如何将链表节点值逆序添加到结果列表中。输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。我们可以顺序遍历链表,将每个节点的值存入数组中,然后将数组反转。假设我们有一个链表:1 -> 2 -> 3 -> None。我们可以通过一个例子来说明这个递归函数。函数并通过递归逆序打印链表的节点值。我们可以使用递归的方式,先递归得到。之后的节点反过来的值列表,然后将。时,函数返回一个空列表。,这是链表的逆序打印结果。的值加到列表的末尾。原创 2024-07-24 15:59:56 · 879 阅读 · 0 评论 -
7. 重建二叉树
由于我们每一次都需要在中序序列中找到根节点的位置,因此我们可以使用哈希表。输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。对应中序序列的范围为【第。对应中序序列的范围为【第。来存储中序序列的值和索引,这样可以将查找的时间复杂度降低到。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。,表示当前子树,对应前序序列的范围为【第。个节点作为根节点,创建一个树节点,其中。对应中序序列的范围为【第。2)否则,我们取中序序列的第。,对应前序序列的范围为【第。,对应前序序列的范围为【第。原创 2024-08-09 23:35:49 · 916 阅读 · 0 评论 -
9. 用两个栈实现队列
分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,如果两个栈都为空,说明队列中没有元素,返回。用两个栈实现一个队列。队列的声明如下,请实现它的两个函数。我们可以使用两个栈来实现队列,其中一个栈。用来存储输入的元素,另一个栈。中的元素逐个弹出并压入栈。方法时,我们将元素压入。不为空,我们直接弹出栈。为队列中的元素个数。原创 2024-08-10 10:43:15 · 854 阅读 · 0 评论 -
10- I. 斐波那契数列
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。F(N) = F(N - 1) + F(N - 2), 其中 N > 1.,求斐波那契(Fibonacci)数列的第。次循环,每次循环中,计算。原创 2024-08-10 10:51:51 · 726 阅读 · 0 评论 -
10- II. 青蛙跳台阶问题
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。这实际上可以转换为斐波那契数列的问题。级台阶跳一级上去,也可从第。级的台阶总共有多少种跳法。次循环,每次循环中,计算。级台阶跳两级上去,即。原创 2024-08-10 11:40:27 · 512 阅读 · 0 评论 -
11. 旋转数组的最小数字
【二分查找 红蓝染色法-哔哩哔哩】 https://b23.tv/hOp1tOJ【搜索旋转排序数组【基础算法精讲 05】-哔哩哔哩】 https://b23.tv/AnTPDwV二分核心在于找到分类属性,从而进行两种分类通过相邻值对比,区分出山顶左 和 山顶右,进而二分:nums[0]作为一种分界线,区分出nums[0]的左 和 右。原创 2024-08-10 22:31:50 · 631 阅读 · 0 评论 -
14- I. 剪绳子
可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。段(m、n都是整数,n>1并且m>1),每段绳子的长度记为。时,由于题目要求至少剪一次,因此。的绳子,请把绳子剪成整数长度的。时,我们尽可能多地拆分。原创 2024-08-11 10:50:56 · 844 阅读 · 0 评论 -
14- II. 剪绳子 II
可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。段(m、n都是整数,n>1并且m>1),每段绳子的长度记为。不能拆分成至少两个正整数的和,因此。的绳子,请把绳子剪成整数长度的。时,我们尽可能多地拆分。,当剩下的最后一段为。原创 2024-08-11 10:55:00 · 755 阅读 · 0 评论 -
12. 矩阵中的路径
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。我们需要枚举矩阵中的每个位置,然后对于每个位置,我们最多需要搜索三个方向。例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。那么问题的转换为如何采用深度优先搜索的方法寻找字符串。,以该位置为起点,采用深度优先搜索的方法寻找字符串。#a输出为"ab"bc"cd"de"ef"fg",否则在枚举完所有的位置后,返回。开始,且当前将要匹配的字符为。分别为矩阵的行数和列数,而。原创 2024-08-11 12:45:33 · 954 阅读 · 0 评论 -
13. 机器人的运动范围
的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。过程中,为了避免重复搜索同一个单元格,我们可以使用数组或哈希表记录所有访问过的节点。由于部分单元格不可达,因此,我们不能直接枚举所有坐标点。出发,搜索所有可达的节点,记录答案。地上有一个m行n列的方格,从坐标。分别为方格的行数和列数。原创 2024-08-11 14:00:56 · 864 阅读 · 0 评论 -
15. 二进制中 1 的个数
n = 4294967293 (控制台输入 11111111111111111111111111111101,部分语言中 n = -3)编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为。的二进制表示中最右边的 1**,因此不断执行。中,共有 31 位为 '1'。根据位运算的性质,我们知道**中,共有一位为 '1'。的二进制表示中最右边的。,统计执行次数即可。,统计执行次数即可。原创 2024-08-11 14:26:49 · 711 阅读 · 0 评论 -
16. 数值的整数次方
2的5次方=2的[101]2进制次方=2的[2的0次方+2的2次方],其中2的2次方 是 (2的0次方)的2次方a*=a。不得使用库函数,同时不需要考虑大数问题。,即计算 x 的 n 次幂函数(即,x。快速幂算法的核心思想是将幂指数。拆分为若干个二进制位上的。原创 2024-08-13 10:01:47 · 994 阅读 · 0 评论 -
17. 打印从 1 到最大的 n 位数
按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。的值比较大,那么直接使用整数会溢出,因此可以使用字符串来模拟,参考以下代码中的。直接根据题意模拟即可。原创 2024-08-13 11:12:47 · 717 阅读 · 0 评论 -
18. 删除链表的节点
给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。返回删除后的链表的头节点。我们先创建一个虚拟头节点。原创 2024-08-13 11:19:22 · 836 阅读 · 0 评论 -
19. 正则表达式匹配
因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。在本题中,匹配是指字符串的所有字符匹配整个模式。".*" 表示可匹配零个或多个('*')任意字符('.')。过程中,我们可以使用记忆化搜索,避免重复计算。"a" 无法匹配 "aa" 整个字符串。,表示空字符串和空正则表达式是匹配的。个字符开始是否匹配。原创 2024-08-13 17:08:33 · 1005 阅读 · 0 评论 -
22. 链表中倒数第 k 个节点
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。步,然后快慢指针同时向前走,直到快指针走到链表尾部,此时慢指针指向的节点就是倒数第。个节点,从头节点开始,它们的值依次是。我们可以定义快慢指针。原创 2024-08-14 14:41:44 · 619 阅读 · 0 评论 -
21. 调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。[3,1,2,4] 也是正确的答案之一。每次向右移动一位,直到遍历完整个数组。指向当前最后一个奇数的下一个位置。接下来,我们从左到右遍历数组,当。是奇数时,我们将其与。原创 2024-08-14 14:58:29 · 740 阅读 · 0 评论 -
20. 表示数值的字符串
的第一个非空格字符和最后一个非空格字符。请实现一个函数用来判断字符串是否表示。遍历结束后,我们返回。(包括整数和小数)。,即是否出现过数字。原创 2024-08-16 11:02:45 · 691 阅读 · 0 评论 -
24. 反转链表
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。递归反转链表的第二个节点到尾部的所有节点,然后。,遍历链表,将每个节点依次插入。插在反转后的链表的尾部。原创 2024-08-19 09:08:12 · 1007 阅读 · 0 评论 -
25. 合并两个排序的链表
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。中有没有一个为空,如果有一个为空,那么我们直接返回另一个链表即可。后面,然后将指针向后移动一位。我们先创建一个虚拟头结点。的值,将较小的值接在。分别为两个链表的长度。分别为两个链表的长度。原创 2024-08-19 11:37:32 · 1080 阅读 · 0 评论 -
26. 树的子结构
中,我们首先判断树 A 和树 B 是否为空,如果其中有一个为空,则树 B 不是树 A 的子结构,返回。否则,递归判断树 A 的左子树是否包含树 B,以及树 A 的右子树是否包含树 B。输入两棵二叉树A和B,判断B是不是A的子结构。返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。,用于判断树 A 中以节点 A 为根节点的子树是否包含树 B。B是A的子结构, 即 A中有出现和B相同的结构和节点值。,判断树 A 是否包含树 B。,则树 B 是树 A 的子结构,返回。原创 2024-08-19 15:22:42 · 713 阅读 · 0 评论 -
29. 顺时针打印矩阵
记录每个元素是否被访问过。每次我们访问到一个元素后,将其标记为已访问,然后按照当前的方向前进一步,如果前进一步后发现越界或者已经访问过,则改变方向继续前进,直到遍历完整个矩阵。输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。注意:比较下面两段代码区别(变量的更新方式不同)分别表示当前访问到的元素的行和列,用。从外往里一圈一圈遍历并存储矩阵元素即可。表示当前的方向,用数组或哈希表。分别是矩阵的行数和列数。分别是矩阵的行数和列数。原创 2024-08-19 17:00:22 · 945 阅读 · 0 评论 -
27. 二叉树的镜像
我们先判断根节点是否为空,如果为空,直接返回空。如果不为空,我们交换根节点的左右子树,然后递归地交换左子树和右子树。是二叉树的节点个数。最坏情况下,二叉树退化为链表,递归深度为。请完成一个函数,输入一个二叉树,该函数输出它的镜像。原创 2024-08-20 11:36:52 · 779 阅读 · 0 评论 -
28. 对称的二叉树
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。例如,二叉树 [1,2,2,3,4,4,3] 是对称的。,分别代表两棵树的根节点。的左子树和右子树是否对称。我们设计一个递归函数。原创 2024-08-20 14:30:30 · 770 阅读 · 0 评论 -
30. 包含 min 函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。--> 返回 -3.minStack.min();--> 返回 -2.时间复杂度:对于每个操作,时间复杂度均为。用来存储当前栈中的最小值。我们用两个栈来实现,其中。原创 2024-08-20 16:45:53 · 706 阅读 · 0 评论 -
31. 栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。序列中下一个要弹出的值,如果是就循环把栈顶元素弹出。序列已经到末尾,说明是一个合法的序列,否则不是。依次压入栈中,压入后检查这个数是不是。1 不能在 2 之前弹出。原创 2024-08-21 09:50:28 · 760 阅读 · 0 评论 -
32 - I. 从上到下打印二叉树
我们可以通过 BFS 遍历二叉树,将每一层的节点值存入数组中,最后返回数组即可。从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。原创 2024-08-21 11:17:21 · 993 阅读 · 0 评论 -
32 - II. 从上到下打印二叉树 II
我们可以使用 BFS 的方法来解决这道题。从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。最后返回答案数组即可。是二叉树的节点个数。原创 2024-08-21 11:45:09 · 885 阅读 · 0 评论 -
32 - III. 从上到下打印二叉树 III
为了实现锯齿形层序遍历,我们每次将当前层的节点添加到结果数组之前,先判断一下当前结果数组的长度,如果是奇数,就将当前层的节点反转一下。之后把当前层的节点添加到结果数组中即可。请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。原创 2024-08-24 10:27:04 · 824 阅读 · 0 评论 -
33. 二叉搜索树的后序遍历序列【难】
【LeetCode力扣刷题 | 剑指Offer 33. 二叉搜索树的后序遍历序列(思路讲解及Python3代码实现)程序员面试手撕代码必刷题库】 https://www.bilibili.com/video/BV1FK4y1j73k/?后序遍历的最后一个元素为根节点,根据二叉搜索树的性质,根节点左边的元素都小于根节点,根节点右边的元素都大于根节点。后序遍历的顺序为“左、右、根”,如果我们从右往左遍历数组,那么顺序就变成“根、右、左”,根据二叉搜索树的性质,右子树所有节点值均大于根节点值。原创 2024-08-27 00:21:40 · 693 阅读 · 0 评论 -
34. 二叉树中和为某一值的路径
从根节点开始,递归遍历每个节点,每次递归时,将当前节点值加入到路径中,然后判断当前节点是否为叶子节点,如果是叶子节点并且路径和等于目标值,则将该路径加入到结果中。如果当前节点不是叶子节点,则递归遍历其左右子节点。递归遍历时,需要将当前节点从路径中移除,以确保返回父节点时路径刚好是从根节点到父节点。路径总和等于给定目标和的路径。是指没有子节点的节点。原创 2024-08-27 14:32:34 · 899 阅读 · 0 评论 -
35. 复杂链表的复制
遍历链表,将链表中的每个节点都复制一份,然后将原节点和复制节点的对应关系存储在哈希表中,同时连接好复制节点的。遍历链表,将链表中的每个节点都复制一份,然后将复制节点插入到原节点的后面。函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个。接下来再遍历链表,根据哈希表中存储的对应关系,将复制节点的。给定的链表为空(空指针),因此返回 null。最后再遍历链表,将链表拆分成原链表和复制链表。指针指向下一个节点,还有一个。指针指向链表中的任意节点或者。接下来再遍历链表,根据原节点的。原创 2024-08-28 20:49:34 · 736 阅读 · 0 评论 -
36. 二叉搜索树与双向链表
对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。下图展示了上面的二叉搜索树转化成的链表。二叉搜索树的中序遍历是有序序列,因此可以通过中序遍历得到有序序列,过程中构建双向链表。遍历结束,将头节点和尾节点相连,返回头节点。为二叉搜索树的节点个数。原创 2024-08-28 23:58:59 · 699 阅读 · 0 评论 -
37. 序列化二叉树【难】
我们可以采用层序遍历的方式对二叉树进行序列化,即从根节点开始,依次将二叉树的节点按照从上到下、从左到右的顺序加入队列中,然后将队列中的节点依次出队。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。反序列化时,我们将序列化字符串按照分隔符进行切分,得到一个字符串数组,然后依次将字符串数组中的元素加入队列中。,则将其转换为整数后作为节点的值,然后将该节点加入队列中,否则将其置为。请实现两个函数,分别用来序列化和反序列化二叉树。原创 2024-08-29 14:43:24 · 768 阅读 · 0 评论 -
38. 字符串的排列【难】
【LeetCode刷题力扣题解 | 剑指Offer 38. 字符串的排列 | 思路讲解及Python3代码实现】 https://www.bilibili.com/video/BV1cK4y1s7tN/?你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。,即从第 0 个位置开始填入字符。最后返回答案数组即可。输入一个字符串,打印出该字符串中字符的所有排列。个位置上填入一个字符,这个字符可以从。个位置,我们需要在第。我们在主函数中调用函数。次排列,每次排列需要。,表示当前排列到了第。原创 2024-08-29 18:33:22 · 883 阅读 · 0 评论 -
39. 数组中出现次数超过一半的数字
如果存在多数,那么该候选值就是多数值。在第二次遍历中,只需要简单地计算候选值的频率,以确认是否是多数值。由于本题已经明确说明存在多数值,所以第一次遍历结束后,直接返回 m 即可,无需二次遍历确认是否是多数值。数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。你可以假设数组是非空的,并且给定的数组总是存在多数元素。一般而言,摩尔投票法需要对输入的列表进行。在第一次遍历中,我们生成候选值。对于输入列表中每一个元素。原创 2024-08-29 19:03:00 · 1262 阅读 · 0 评论 -
40. 最小的 k 个数
虽然这一步是必要的,但快速选择的核心优化之处在于减少了数组划分和递归的次数,因此优化了整体时间复杂度。代码中不再递归排序整个数组的两部分,而是专注于一部分(左或右),根据 k的大小来判断接下来要处理的子数组部分,从而有效减少不必要的排序操作。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。,如果是,就直接返回划分点左边的数即可,否则根据划分点的位置决定下一步划分的区间。,如果超过了,就将堆顶元素弹出。,我们先将其加入优先队列中,然后判断优先队列的大小是否超过。原创 2024-08-30 19:55:24 · 1101 阅读 · 0 评论