![](https://img-blog.csdnimg.cn/20201014180756754.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
剑指offer
薛定谔的猫96
2年前端练习生
展开
-
剑指 offer 数组算法题:唯一只出现一次的数字(其余均出现两次)
给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。,任何数和 0 做异或运算,结果仍然是原来的数;任何数和其自身做异或运算,结果是 0;异或运算满足交换律和结合律。因此数组中的全部元素的异或运算结果即为数组中只出现一次的数字。原创 2023-07-15 09:29:15 · 351 阅读 · 0 评论 -
剑指 offer 动态规划算法题:最小路径和
给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。dp(i, j) 表示到达第i行第j列的最小路径和 (i, j 均从0开始)说明:每次只能向下或者向右移动一步。原创 2023-07-14 09:56:32 · 338 阅读 · 0 评论 -
剑指 offer 动态规划算法题:矩形覆盖
和斐波那契数列一样,n个2*1的小矩形无重叠地覆盖一个2*n的大矩形的方法数等于 n - 1 个2*1的小矩形无重叠地覆盖一个2*(n - 1)的大矩形的方法数 与 n - 2 个2*1的小矩形无重叠地覆盖一个2*(n - 2)的大矩形的方法数 之和,即,f(n) = f(n - 1) + f(n-2)只是初始值不同, f(0) = 0, f(1) = 1, f (2) = 2。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?比如n=3时,2*3的矩形块有3种覆盖方法。原创 2023-07-14 09:56:25 · 330 阅读 · 0 评论 -
剑指 offer 动态规划算法题:地下城游戏
如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。因为需要满足 dp[i][j] ≥ 1 且 dp[i][j] + dungeon[i][j] ≥ dp[i][j+1]:表示进入第i行第j列后健康点数dp[i][j] + dungeon[i][j]需要不小于进入下一个格子之前的最低健康点数dp[i][j+1])。因为需要满足 dp[i][j] ≥ 1 且 dp[i][j] + dungeon[i][j] >= Math.min(dp[i][j + 1], dp[i + 1][j])。原创 2023-07-14 09:56:20 · 421 阅读 · 0 评论 -
剑指 offer 动态规划算法题:打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。状态转移方程:dp[i] = Math.max(nums[i] + dp[i - 2], dp[i - 1]);dp[i] 表示从[0, i] 区间内房屋能偷窃到的最高金额。原创 2023-07-14 09:56:14 · 313 阅读 · 0 评论 -
剑指 offer 动态规划算法题:不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。, 其状态转移方程为 dp(i, j) = dp(i - 1, j) + dp(i, j - 1);dp(i, j)表示到达第i行第j列有多少条路径(i, j 均从0开始)。即优化空间复杂度,使用dp表(paths),即滚动数组,初始均为 1。数组的元素总是等于当前列上一行(paths[j]) + 当前行上一列(paths[j - 1])。原创 2023-07-14 09:56:06 · 323 阅读 · 0 评论 -
剑指 offer 动态规划算法题:0-1背包问题
状态转移方程:dp[i][j] = Math.max(value[i] + dp[i-1][j - weights[i]], dp[i-1][j]);前提是 j >= weights[i]。利用滚动数组,优化空间复杂度:dp[j] = Math.max(value[i] + dp[j - weights[i], dp[j])。dp[i][j] 表示最大重量为 j 的背包中所能包含的 [0, i]区间内的物品的最大价值。原创 2023-07-14 09:55:59 · 334 阅读 · 0 评论 -
剑指 offer 数学算法题:十进制转k进制
首先根据k制作一个进制数字数组,然后将十进制数进行除k取余,更新十进制数为除数,并逆序排余数,直到除数为0。:给定一个十进制数,请转成k进制(k不大于36),如果k大于10,则从A开始算。原创 2023-07-14 09:55:54 · 188 阅读 · 0 评论 -
剑指 offer 数学算法题:实现大数相乘
乘数 num1 位数为 M,被乘数 num2 位数为 N, num1 x num2 结果 res 最大总位数为 M+N,而且num1[i] x num2[j] 的结果再加上其第二位对应的结果数组中的res[i+j+1]得到一个sum,sum的个位就是新的res[i+j+1],sum的十位加上res[i+j]就是新的res[i+j]。:给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。原创 2023-07-14 09:55:46 · 312 阅读 · 0 评论 -
剑指 offer 数学算法题:实现大数相加
由于最大的安全整数是16位,因此从后往前每15位转换为数字相加并且考虑进位,然后再将每部分字符串拼接。需要注意的是,某一部分相加的结果如果位数为16位,说明需要进位,如果位数为小于等于15位时且存在一个加数的位数等于15位,这部分的结果前面需要补0。:给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。原创 2023-07-14 09:55:34 · 194 阅读 · 0 评论 -
剑指 offer 数学算法题:不用加减乘除做加法
对两个数字进行位异或运算的结果即为不考虑进位的情况下的求和,而对两个数字进行与运算后左移一位即为进位值,两者相加,直到后者为 0 即不存在进位。:写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。原创 2023-07-14 09:55:27 · 58 阅读 · 0 评论 -
剑指 offer 数学算法题:出现1的次数
而从 567 到 1234567 这个范围内,百位上1出现的次数为 出现的 1 的次数为:⌊ n / 1000 ⌋ × 100, 而 从 0 到 567 百位出现 1 的次数为: min(max(n mod 1000 - 100 + 1, 0), 100),因为 若 n mod 1000 > 200 则出现 100 次,小于 200 则出现 n mod 1000 - 100 + 1, 小于100 则出现 0 次。例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。原创 2023-07-15 09:29:55 · 360 阅读 · 0 评论 -
剑指 offer 数学算法题:圆圈中最后剩下的数(小孩报数问题?)
求出这个圆圈里剩下的最后一个数字。假设删除一个数后的序列 m + 1, m + 2, ... , n, 0, 1, 2, m - 1, 继续删除最后求得的解为 x = f(n -1, m) = f(n, m) - m;那么 f(n, m) = (f(n- 1) + m) % n,其中 f (1, m) = 0。可以使用动态规划,初始值为 f (1, m) = 0,从 2 到 n 开始遍历到 n 即可求得 f(n, m) = (f(n- 1) + m) % n。原创 2023-07-15 09:29:59 · 451 阅读 · 0 评论 -
剑指 offer 数学算法题:和为S的连续正数序列
循环中,每轮判断滑动窗口内元素和与目标值 target 的大小关系,若相等则记录结果并移动左边界 i (以减小窗口内的元素和),若大于 target 则移动左边界 i (以减小窗口内的元素和),若小于 target 则移动右边界 j (以增大窗口内的元素和)。在已知 target 和 i 的情况下,通过求根公式计算出 j,当计算出的 j > i 且 j 是整数0,将 i 到 j 的所有数字构成的序列添加到结果数据中即可。若等于 target, 将 i 到 j 的所有数字构成的序列添加到结果数据中即可。原创 2023-07-15 09:30:05 · 506 阅读 · 0 评论 -
剑指 offer 数学算法题:求1+2+3+...+n
求 1+2+...+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?使用短路表达式,当 n!== 0 的时候进行递归累加。原创 2023-07-15 09:30:20 · 313 阅读 · 0 评论 -
剑指 offer 数学算法题:数值的整数次方
当我们要计算 x^n时,我们可以先递归地计算出 y=x ⌊n/2⌋,其中 ⌊a⌋ 表示对 a 进行下取整;根据递归计算的结果,如果 n 为偶数,那么 x^n = y^2;如果 n 为奇数,那么 x^n = y^2 * x;: 实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。,其中 b = [0, 1]是指数 n 的二进制位。因此每次舍弃n 的最低位,如果从右往左的二进制位是 1,将贡献。通过判断 n 的正负,若为负数, x 即为倒数,然后累计计算 abs(x) 次即可。原创 2023-07-15 09:30:11 · 438 阅读 · 0 评论 -
剑指 offer 数学算法题:二进制中1的个数
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为 汉明重量).当检查第 i位时,我们可以让 n 与 2^i 进行与运算,当且仅当 n 的第 i 位为 1 时,运算结果不为 0。n & (n−1)会将n 的最右边的那个1变成0,直到n 等于0,运算次数就等于 n 的二进制位中 1 的个数。原创 2023-07-15 09:30:26 · 467 阅读 · 0 评论 -
剑指 offer 动态规划算法题:丑数
定义数组dp,其中 dp[i - 1] 表示第 i 个丑数,第 nn 个丑数即为 dp[n]。由于最小的丑数是 1,因此 dp[0]=1。当 1≤ i ≤ n-1 时,令 dp[i]=min(dp[p2]×2,dp[p3]×3,dp[p5]×5), 然后分别比较 dp[i] 和 dp[p2]×2,dp[p3]×3,dp[p5]×5 是否相等,如果相等则将对应的指针加 1。从 1 开始判断遍历,判断是否丑数(只有 2, 3, 5 作为因子),若是丑数 n 自减,直到 n 等于 1,返回即可。原创 2023-07-15 09:30:33 · 341 阅读 · 0 评论 -
剑指 offer 动态规划算法题:青蛙变态跳台阶
迭代法,f(n) 指的是跳上一个n级的台阶有多少种跳法,那么如果第一步跳 1 级,那么剩下 n - 1 级台阶即有 f(n - 1) 种跳法,如果第一步跳 2 级,那么剩下 n - 2 级台阶即有 f(n - 2) 种跳法, 依次类推,第一次跳 n - 1 级,有 f(1) = 1种跳法,第一次跳 n 级,有 f (0) = 1 中跳法,将其累加 ,f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(1) + f(0);:一只青蛙一次可以跳上1级台阶,也可以跳上2级……原创 2023-07-13 09:39:10 · 75 阅读 · 0 评论 -
剑指 offer 动态规划算法题:斐波那契数列(青蛙普通跳台阶)
斐波那契数列的定义如下:F(0) = 0, F(1) = 1,F(N) = F(N - 1) + F(N - 2), 其中 N > 1.斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。对于青蛙普通跳台阶,和斐波那契数列一样,只是初始值不同, f(0) = 0, f(1) = 1, f (2) = 2。直接利用递推公式,进行递归,退出条件为 F(0) = 0, F(1) = 1。,使用两个变量存储前两个数的值,从 1 到n - 1 个遍历即可。原创 2023-07-13 09:38:59 · 72 阅读 · 0 评论 -
剑指 offer 堆算法题:数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。例如, [2,3,4] 的中位数是 3, [2,3] 的中位数是 (2 + 3) / 2 = 2.5。,使用大根堆和小根堆分别保存较小和较大的一半,且在插入时保证,且小根堆比大根堆中元素个数多1或相等,如此一来,在取出时若两个堆元素个数相等,则中位数是两个堆顶元素的一半,否则是中位数是小根堆的堆顶。,首先对于每个插入的元素,在插入时使其有序,取出时只需要取中间的数或中间两个数和的一半即可。原创 2023-07-13 09:38:54 · 173 阅读 · 0 评论 -
剑指 offer 搜索算法题:机器人的运动范围
而其他不连通的蓝色方格区域会随着 k 的增大而连通,且连通的时候也是由上方或左方的格子移动一步得到,因此我们可以将我们的搜索方向缩减为向右或向下。用一个相同维度的二维数组记录是否可以到达,而递归退出条件则是,机器人到达不了 或 已经访问过 或 超出边界,此时返回0,否则可以到达,返回 1 + 向右和向下搜索的结果。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。请问该机器人能够到达多少个格子?原创 2023-07-13 09:38:49 · 176 阅读 · 0 评论 -
剑指 offer 搜索算法题:矩阵中的路径
典型的矩阵搜索问题,可使用 深度优先搜索(DFS)+ 剪枝解决。DFS 通过递归,先朝一个方向搜到底,再回溯至上个节点,沿另一个方向搜索,以此类推。剪枝: 在搜索中,遇到 这条路不可能和目标字符串匹配成功 的情况(例如:此矩阵元素和目标字符不同、此元素已被访问),则应立即返回,称之为可行性剪枝。给定一个 m x n 二维字符网格 board 和一个字符串单词 word。否则,返回 false。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。原创 2023-07-13 09:38:45 · 152 阅读 · 0 评论 -
剑指 offer 树算法题:二叉搜索树与双向链表
2. 遍历到当前节点时,判断若是最左节点,说明是双向链表的头结点,否则将前驱节点的后驱指向当前遍历节点,当前节点的前驱指向 pre,更新前驱节点 pre 为 当前遍历节点。,利用栈来迭代中序遍历,出栈时执行和递归中遍历当前节点相同的操作,同样,遍历结束后,将头结点 head 的前驱指向最后一个节点 pre,将最后一个节点 pre 的后驱指向头结点 head。4. 最后递归结束,将头结点 head 的前驱指向最后一个节点 pre,将最后一个节点 pre 的后驱指向头结点 head。输入一棵二叉搜索树,将该。原创 2023-07-13 09:38:41 · 62 阅读 · 0 评论 -
剑指 offer 树算法题:序列化二叉树
实现两个函数,分别用来序列化(serialize)和反序列化(deserialize)二叉树。你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。则序列化为'None,',否则序列化为'该节点值,该节点左子树的序列化结果该节点右子树的序列化结果'。然后分别对左子树、右子树递归进行反序列化。直接使用JSON.stringify 和 JSON.parse 进行序列化和反序列化即可。原创 2023-07-13 09:38:34 · 48 阅读 · 0 评论 -
剑指 offer 树算法题:二叉树的下一个节点
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。原创 2023-07-13 09:37:53 · 72 阅读 · 0 评论 -
剑指 offer 树算法题:树的子结构
首先,任何树不是空树的子结构,空树也不是任何树的子结构;其次判以当前节点为根的树是否包含断 B 树;如果不包含,再判断B是否是其左子树或其右子树的子结构。输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构),B是A的子结构,即 A中有出现和B相同的结构和节点值。子结构与子树不同,子结构可以在叶子节点不完全相同,即子树一定是子结构,子结构不一定是子树。,由于树是对象,可以将其序列化成字符串,判断序列化A中是否包含序列化B。原创 2023-07-13 09:38:29 · 59 阅读 · 0 评论 -
剑指 offer 树算法题:二叉搜索树的第k个节点
因此可以在遍历的过程中用一个变量来记录遍历的次序,当遍历到第k个节点即可。或者可以直接遍历得到遍历结果数组,取第k个值。如果需要求的是第k小的则是采用中序遍历。给定一棵二叉搜索树,请找出其中第 k 大的节点的值。二叉搜索树即二叉查找树或二叉排序树,它的。原创 2023-07-13 09:37:46 · 50 阅读 · 0 评论 -
剑指 offer 树算法题:二叉搜索树的后序遍历序列
因为二叉搜索树满足左子树 < 根节点 < 右子树,其中序遍历是有序的,而且中序、后序分别对应栈的压入、弹出序列(首先左子树入栈,左子树弹出,然后根节点、右子树入栈,右子树、根节点弹出),因此可以通过将当前后序遍历排序, 然后判断中序,后序是否满足栈的压入、弹出即可。输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。原创 2023-07-12 11:10:44 · 192 阅读 · 0 评论 -
剑指 offer 树算法题:对称二叉树
因此,通过「同步移动」两个指针的方法来遍历这棵树, p 指针和 q 指针一开始都指向这棵树的根,随后 p 右移时,q 左移,p 左移时,q 右移。每次检查当前 p 和 q 节点的值是否相等,如果相等再判断左右子树是否镜像对称。,如果一个树的左子树与右子树镜像对称,那么这个树是对称的。请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。原创 2023-07-12 11:06:53 · 208 阅读 · 0 评论 -
剑指 offer 树算法题:二叉树中和为某一值的路径
深度优先搜素(dfs)法,枚举每一条从根节点到叶子节点的路径。当我们遍历到叶子节点,且此时路径和恰为目标和时,就找到了一条满足条件的路径。路径是根节点开始到叶节点结束的,目的是需要找出的所有符合条件(即路径节点和等于给定整数)的路径。输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。原创 2023-07-12 11:04:37 · 97 阅读 · 0 评论 -
剑指 offer 树算法题:平衡二叉树
首先,平衡二叉树的平衡性即,左子树与右子树的高度差的绝对值不大于1。即在遍历二叉树节点的过程中需要求该节点的左子树和右子树的高度差,自底向上的递归求树高度更为简单(参考)。输入一棵二叉树,判断该二叉树是否是平衡二叉树(不考虑其是不是排序二叉树,只需要考虑其平衡性)。原创 2023-07-12 10:33:37 · 67 阅读 · 0 评论 -
剑指 offer 树算法题:镜像二叉树
请完成一个函数,输入一个二叉树,该函数输出它的镜像。其镜像二叉树,其镜像二叉树,即左右子树进行对调,递归对调即可:先分别递归求得左右子树的镜像,然后将左子树镜像与右子树镜像分别挂着右左子树上,即对调原创 2023-07-12 10:29:44 · 173 阅读 · 0 评论 -
剑指 offer 树算法题:从上到下打印二叉树
由题目分析,是层序遍历的过程,因此直接层序遍历即可,如果要求返回的是二维数组,即每一层节点数组构成的数组,仅仅需要在每一层遍历开始构建数组,遍历完该层后将数组加入到外层数组中。还有就是可能要求之字形的打印(即偶数层的打印是从右到左),使用一个层遍历初始方向标志变量,对于每一层true则push,false则unshift,该变量初始为true,每打印一层取反,遍历完该层后将数组加入到外层数组中即可。从上往下打印出二叉树的每个节点。原创 2023-07-12 10:27:11 · 79 阅读 · 0 评论 -
剑指 offer 树算法题:二叉树的深度
设定初始树深度depth为0,通过自根节点向下遍历,其中每向下遍历即更新当前路径的深度count,直到叶节点时更新初始深度depth为当前路径的深度count和depth的较大值。同时,每个路径达到当前节点为null,跳出当前递归路径。输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。,可以利用队列来保存[当前节点,该节点层数root节点为1]信息数组,层序。,由于每个树节点的深度等于其左子树深度和右子树深度的较大者+1。原创 2023-07-12 10:13:02 · 78 阅读 · 0 评论 -
剑指 offer 树算法题:重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列[1,2,4,7,3,5,6,8]和中序遍历序列[4,7,2,1,5,3,8,6],则重建二叉树并返回。在中序遍历序列中找到前序遍历序列的第一个节点1,该节点将中序遍历序列分成。即为右子树的前序遍历序列[3,5,6,8],如此递归下去。即为左子树的前序遍历序列[2,4,7]以及。两个部分,而在前序遍历序列中紧接着的。,同理,只不过后序的根节点在最后。原创 2023-07-12 10:20:18 · 72 阅读 · 0 评论 -
剑指 offer 链表算法题:链表中环的入口节点
遍历链表,快指针走两步,慢指针每次走一步,快慢指针必定在环内相遇,此时快指针走过 a + n(b + c) + b = a + (n+1)b + nc, 而慢指针走过的路程 a + b (因为一定还没走完环的第一圈),两者满足 a + (n+1)b + nc = 2(a + b), 所以a = c + (n − 1)(b + c),即链表头结点到环入口节点的距离 = 相遇点到环入口距离 + (n - 1)*环,只需要让两新指针分别从头结点和相遇节点单步出发,直到相遇即可。如果链表无环,则返回 null。原创 2023-07-12 09:46:16 · 182 阅读 · 0 评论 -
剑指 offer 链表算法题:两个链表的第一个公共节点
既然公共节点及其之后的节点完全相同,即不同的是公共节点之前的部分,也就可能存在一个长度差 diff,通过遍历两个链表的长度可以求出diff,让长的链表先遍历diff个节点,以此开始的两个链表的长度相同,那么当遍历到相同节点即第一个公共节点。两个链表的公共节点是指从公共节点开始的所有节点是两个链表的共有部分(输入两个链表,找出它们的第一个公共结点。原创 2023-07-12 09:46:05 · 72 阅读 · 0 评论 -
剑指 offer 链表算法题:删除链表中的重复节点
中,存在重复的结点,请删除该链表中重复的结点,分为重复结点保留(链表1->2->3->3->4->4->5 处理后为 1->2->3->4->5)和重复的结点不保留(链表1->2->3->3->4->4->5 处理后为 1->2->5)两种情况,返回链表头指针。从头节点开始遍历,判断当前节点下一个节点是否等于当前节点,如果相等,则当前节点的下一节点为下下节点,直到不等于或者当前节点下一节点为空。原创 2023-07-11 21:56:41 · 110 阅读 · 0 评论 -
剑指 offer 链表算法题:复杂链表的复制
首先对复杂链表进行遍历,在每个节点后面复制一个与当前节点相同的节点(先不理会random指针),即1 -> 2->3-->4->5->null 变成 1 -> 1-> 2->2->3-->3->4->4->5->5->null;最后再遍历一次,将原链表的节点指向原来的下一个节点,复制链表的节点指向下一个复制的节点,分离成原链表和复制链表,注意判断最后一个复制节点是否为null。,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)原创 2023-07-11 21:53:13 · 236 阅读 · 0 评论