自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(222)
  • 收藏
  • 关注

原创 经典算法实例:好子集的数目(二)

注意到 f[i][mask] 只会从 f[i − 1][..] 转移而来,并且 f[i − 1][..] 中的下标总是小于 mask,因此我们可以使用类似 0 - 1 背包的空间优化方法,在遍历 mask 时从 210 − 1 到 1 逆序遍历,这样就只需要使用一个长度为 210 的一维数组做状态转移了。这样一来,我们定义 f[i][mask] 表示当我们只选择 [2,i] 范围内的数,并且选择的数的质因数使用情况为 mask 时的方案数。空间复杂度:O(2π(C)),即为动态规划需要使用的空间。

2026-09-01 18:18:37 168

原创 经典算法实例:好子集的数目(一)

是通过删除 nums 中一些(可能一个都不删除,也可能全部都删除)元素后剩余元素组成的数组。如果两个子集删除的下标不同,那么它们被视为不同的子集。给你一个整数数组 nums。如果 nums 的一个子集中,所有元素的乘积可以表示为一个或多个 互不相同的质数 的乘积,那么我们称它为 好子集。子集的数目对 109 + 7。请你返回 nums 中不同的。

2026-09-01 17:05:53 226

原创 浅谈:如何正确且专业的对待面试

也许你并没有写出完美的代码,但是如果你展现出严谨的逻辑思维,训练有素的解题思路,从容自信的态度,对技术深深的热爱(热情不够,演技来凑!大家就想象面试官是辅助你通关的角色,在面试的全过程都要注重跟 ta 的交流互动,让他感知到你的优秀!这样的努力当然是值得夸夸的,但是遗憾的是,在实际的面试中,“做出题目”和“面试通过”并不能直接画等号。在校招场景中,大家经验相对都薄弱,而企业也愿意培养新人,所以展现出自己的潜力就更加重要。

2026-08-29 12:10:11 222

原创 一文读懂:最长特殊序列

例如,"abc" 是 "aebdc" 的子序列,因为删除 "aebdc" 中斜体加粗的字符可以得到 "abc"。"aebdc" 的子序列还包括 "aebdc" 、 "aeb" 和 "" (空字符串)。时间复杂度:O(n) ,其中 n 是字符串 a 的长度。给你两个字符串 a 和 b ,请返回 这两个字符串中 最长的特殊序列 的长度。「最长特殊序列」 定义如下:该序列为 某字符串独有的最长子序列(即不能是其他字符串的子序列)。字符串 s 的子序列是在从 s 中删除任意数量的字符后可以获得的字符串。

2026-08-26 08:46:51 186

原创 一文读懂:N叉树的后序遍历(二)

接上文,我们讲第二个解题思路。

2026-08-22 13:06:22 185

原创 一文读懂:N叉树的后序遍历(一)

给定一个 n 叉树的根节点 root ,返回其节点值的后序遍历。n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。

2026-08-22 09:25:42 182

原创 经典算法实例应用:N叉树的后序遍历(一)

递归思路比较简单,N 叉树的前序遍历与二叉树的后序遍历的思路和方法基本一致,可以参考「145. 二叉树的后序遍历」的方法,每次递归时,先递归访问每个孩子节点,然后再访问根节点即可。给定一个 n 叉树的根节点 root ,返回其节点值的后序遍历。n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。

2026-07-23 15:10:28 235

原创 经典算法题:只出现一次的数字

【代码】经典算法题:只出现一次的数字。

2026-07-22 11:19:25 237

原创 算法实例教学:字典序的第K小数字(二)

可以按照层次遍历子树,firsti 指向第 i 层的最左侧的孩子节点, lasti 指向第 i 层的最右侧的孩子节点,根据推理可以知道: firsti = 10 × firsti − 1 ,lasti = 10 × lasti − 1 + 9 ,第 i 层共有 lasti − firsti + 1 个节点,由于所有的节点都需要满足小于等于 n ,所以第 i 层的最右侧节点应该为 min(n,lasti) ,不断迭代直到 firsti > n 则终止向下搜索。依次重复上述操作直到找到 k 小的节点即可。

2026-07-21 16:24:24 207

原创 算法实例教学:字典序的第K小数字(一)

题目要求找到字典序第 k 小的数字,可以将所有的数字都转换成字符串,然后排序找到第 k 小的数字即可,但显然时间复杂度不符合要求。给定整数 n 和 k ,返回 [1, n] 中字典序第 k 小的数字。

2026-07-21 13:18:08 221

原创 思考:要做到Bug Free需培养怎样的思维?

学习优质的写法慢慢形成自己的风格。倒不如先学习一个简单的记录答案写法,保证自己遇到这类问题肯定能写对,然后随着刷题量的增加慢慢领悟其他写法。的水平是几乎不可能的,只有勤练习,才可以逐渐全面自己思考问题的角度,减少编写代码时候的漏洞。接着后续再提升自己思维能力和考虑问题的周全性,同时积累一定的做题经验,面对题目时要能快速发现坑点,有能力构造一些特殊数据,测试自己程序的健壮性。总的思路可分为几个步骤,第一步先练好写基本代码的能力,做到想实现什么功能就能不假思索地码出简洁的代码来、指哪打哪、快准稳狠。

2026-07-18 13:35:55 199

原创 经典算法实例应用:交替位二进制数(二)

当且仅当输入 n 为交替位二进制数时,a 的二进制表示全为 1(不包括前导 0)。这里进行简单证明:当 a 的某一位为 1 时,当且仅当 n 的对应位和其前一位相异。当 a 的每一位为 1 时,当且仅当 n 的所有相邻位相异,即 n 为交替位二进制数。将 a 与 a+1 按位与,当且仅当 a 的二进制表示全为 1 时,结果为 0。这里进行简单证明:当且仅当 a 的二进制表示全为 1 时,a+1 可以进位,并将原最高位置为 0 ,按位与的结果为 0。结合上述两步,可以判断输入是否为交替位二进制数。

2026-07-17 16:33:23 162

原创 经典算法实例应用:交替位二进制数(一)

给定一个正整数,检查它的二进制表示是否总是 0、1 交替出现:换句话说,就是二进制表示中相邻两位的数字永不相同。时间复杂度:O(logn)。输入 n 的二进制表示最多有 O(logn) 位。空间复杂度:O(1)。使用了常数空间来存储中间变量。

2026-07-17 08:43:42 214

原创 经典算法实例应用:自除数

根据自除数的定义,如果一个整数不包含 0 且能被它包含的每一位数整除,则该整数是自除数。判断一个整数是否为自除数的方法是遍历整数的每一位,判断每一位数是否为 0 以及是否可以整除该整数。对于范围内的每个整数,需要 O(log right) 的时间判断是否为自除数。遍历整数的每一位的方法是,每次将当前整数对 10 取模即可得到当前整数的最后一位,然后将整数除以 10。例如,128 是一个 自除数 ,因为 128 % 1 == 0 ,128 % 2 == 0 ,128 % 8 == 0。

2026-07-16 13:22:09 159

原创 算法程序员常考大厂面试题汇总解析

同样的,精通算法也可以解决现实生活中遇到的大多数问题,因为我们通过将其抽象并建模之后,会发现问题的本质是相似的,我们往往可能从某一个基础算法中获得启发,从而高效地解决问题。而达到这一境界,就要求我们首先对基础算法非常了解,并达到熟练运用,融会贯通的地步。(三)给你一个 n*m 的二维数组,每行元素保证递增,每列元素保证递增,试问如何使用优秀的时间复杂度找到某个数字(或者判断不存在)。排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

2026-07-16 09:01:13 358

原创 经典算法实例:旋转字符串(二)

首先,如果 s 和 goal 的长度不一样,那么无论怎么旋转,s 都不能得到 goal ,返回 false。字符串 s+s 包含了所有 s 可以通过旋转操作得到的字符串,只需要检查 goal 是否为 s+s 的子字符串即可。时间复杂度:O(n) ,其中 n 是字符串 s 的长度。KMP 算法搜索子字符串的时间复杂度为 O(n) ,其他搜索子字符串的方法会略有差异。空间复杂度:O(n) ,其中 n 是字符串 s 的长度。KMP 算法搜索子字符串的空间复杂度为 O(n) ,其他搜索子字符串的方法会略有差异。

2026-07-15 13:54:06 222

原创 经典算法实例:旋转字符串(一)

首先,如果 s 和 goal 的长度不一样,那么无论怎么旋转,s 都不能得到 goal,返回 false。在长度一样(都为 n)的前提下,假设 s 旋转 i 位,则与 goal 中的某一位字符 goal[j] 对应的原 s 中的字符应该为 s[(i + j)mod n] 在固定 i 的情况下,遍历所有 j ,若对应字符都相同,则返回 true。若所有的 i 都不能使 s 变成 goal ,则返回 false。如果在若干次旋转操作之后,s 能变成 goal ,那么返回 true。

2026-07-15 07:40:24 231

原创 统计各位数字都不同的数字个数

当 n = 2 时,0 ≤ x < 100 ,x 的选择可以由两部分构成:只有一位数的 x 和有两位数的 x。有两位数的 x 可以由组合数学进行计算:第一位的选择有 9 种,即 1∼9 ,第二位的选择也有 9 种,即 0∼9 中除去第一位的选择。更一般地,含有 d (2 ≤ d ≤ 10)位数的各位数字都不同的数字 x 的个数可以由公式 9 × A9 d-1 计算。给你一个整数 n ,统计并返回各位数字都不同的数字 x 的个数,其中 0 <= x < 10n。

2026-07-14 08:07:10 153

原创 Next数组正确性分析及求解next数组

且在整个 while 的执行过程中变量 i 和 i−j 不会减小,那么这个 while 循环运行的结果就是把这两个变量不断推到最大值。可以知道这两个变量的最大值都是 N,因此 while 循环的执行次数不会超过 2N 次,因此时间复杂度 O(N)。设字符串 s 的长度是 N,p 的长度是 M,我们看估计 contains 方法中 while 循环体的一共执行多少次。我们设置两个量,一个是 i,一个是 i−j,其中 i 的范围 [0,N],i-j 的范围 [0,N]。我们这里给出一般性的说明。

2026-07-13 20:15:44 193

原创 一文读懂:通俗易懂的KMP算法详解

KMP 算法的计算过程启发的过程:上面的暴力方法是基于这样的一个尝试的思路,如果 s 中有一个子串和 p 是匹配的,因为任何一个子串都有一个开头位置,那么这个和 p 匹配的子串当然也有一个开头位置,又因为我们不知道哪个开头位置的子串和 p 是匹配的,因此我们尝试所有可能的开头。这样的查找方法,在遇到 s = “aaaaaaaaaaaaab”,p = “aab” 这样的情况的时候,会使得 p 只有在最后一次匹配的时候,才可以得到匹配。为了便于说明 j 的调整,下面我们举一个明显的例子。

2026-07-12 21:57:04 252

原创 经典算法实例:字符的最短距离

对于后者,我们可以从右往左遍历 s,若 s[i] = c 则记录下此时字符 c 的的下标 idx。遍历的同时更新 answer[i] = min⁡( answer[i],idx−i )。返回一个整数数组 answer ,其中 answer.length == s.length 且 answer[i] 是 s 中从下标 i 到离它 最近 的字符 c 的 距离。对于前者,我们可以从左往右遍历 s,若 s[i] = c 则记录下此时字符 c 的的下 idx。s[i] 到其左侧最近的字符 c 的距离。

2026-07-12 09:45:09 159

原创 三分钟带你读懂:旋转函数

时间复杂度:O(n),其中 n 是数组 nums 的长度。计算 numSum 和第一个 f 消耗 O(n) 时间,后续迭代 n−1 次 f 消耗 O(n) 时间。返回 F(0), F(1), ..., F(n-1) 中的最大值。给定一个长度为 n 的整数数组 nums。生成的测试用例让答案符合 32 位 整数。空间复杂度:O(1)。

2026-07-11 12:57:46 165

原创 经典算法实例应用:三维形体投影面积

在 n x n 的网格 grid 中,我们放置了一些与 x,y,z 三轴对齐的 1 x 1 x 1 立方体。投影 就像影子,将 三维 形体映射到一个 二维 平面上。现在,我们查看这些立方体在 xy 、yz 和 zx 平面上的投影。根据题意,x 轴对应行,y 轴对应列,z 轴对应网格的数值。yz 平面的投影面积等于网格上每一列最大数值之和;zx 平面的投影面积等于网格上每一行最大数值之和。xy 平面的投影面积等于网格上非零数值的数目;时间复杂度:O(n2),其中 n 是网格的行数或列数。

2026-07-10 16:23:44 222

原创 原地交换的思路和算法分析

记数组 nums 的长度为 n。先从 nums 左侧开始遍历,如果遇到的是偶数,就表示这个元素已经排好序了,继续从左往右遍历,直到遇到一个奇数。然后从 nums 右侧开始遍历,如果遇到的是奇数,就表示这个元素已经排好序了,继续从右往左遍历,直到遇到一个偶数。交换这个奇数和偶数的位置,并且重复两边的遍历,直到在中间相遇,nums 排序完毕。时间复杂度:O(n)。原数组中每个元素只遍历一次。空间复杂度:O(1)。原地排序,只消耗常数空间。

2026-07-09 21:28:43 174

原创 经典算法实例应用:最近的请求次数

由于每次收到的请求的时间都比之前的大,因此从队首到队尾的时间值是单调递增的。当在时间 t 收到请求时,为了求出 [t−3000,t] 内发生的请求数,我们可以不断从队首弹出早于 t − 3000 的时间。循环结束后队列的长度就是 [t−3000,t] 内发生的请求数。int ping(int t) 在时间 t 添加一个新请求,其中 t 表示以毫秒为单位的某个时间,并返回过去 3000 毫秒内发生的所有请求数(包括新请求)。我们可以用一个队列维护发生请求的时间,当在时间 t 收到请求时,将时间 t 入队。

2026-07-09 14:57:28 328

原创 一文读懂:序列化和反序列化二叉搜索树

在将后序遍历的数组恢复成二叉搜索树时,不需要先排序得到中序遍历的数组再根据中序和后序遍历的数组来恢复二叉树,而可以根据有序性直接由后序遍历的数组恢复二叉搜索树。二叉搜索树是一种特殊的二叉树,序列化和反序列化过程也可以参照「297. 二叉树的序列化与反序列化」的过程。后序遍历得到的数组中,根结点的值位于数组末尾,左子树的节点均小于根节点的值,右子树的节点均大于根节点的值,可以根据这些性质设计递归函数恢复二叉搜索树。因此,仅对二叉搜索树做「先序遍历」或者「后序遍历」,即可达到序列化和反序列化的要求。

2026-07-08 13:50:30 193

原创 经典算法实例应用:删列造序

你需要找出并删除 不是按字典序升序排列的 列。在上面的例子(下标从 0 开始)中,列 0('a', 'b', 'c')和列 2('c', 'e', 'e')都是按升序排列的,而列 1('b', 'c', 'a')不是,所以要删除列 1。这些字符串可以每个一行,排成一个网格。给你由 n 个小写字母字符串组成的数组 strs,其中每个字符串长度相等。返回你需要删除的列数。

2026-07-07 11:17:48 180

原创 浅谈:编程语言中的那些「锁」事(二)

以 Java 中的锁为例,Java 中有种类丰富的锁,每种锁因其特性的不同,在不同的场景下展现出的效率也是参差不齐的。这就需要我们对锁进行合理的分类,放对位置,才能更好地使用锁。无锁:不锁住资源,多个线程中只有一个能修改资源成功,其它线程会重试。轻量级锁:多个线程竞争同步资源时,没有获取资源的线程自旋等待锁释放。重量级锁:多个线程竞争同步资源时,没有获取资源的线程阻塞等待唤醒。偏向锁:同一个线程执行同步资源时自动获取资源。先尝试插队,插队失败再排队:非公平锁。否:不阻塞(自旋锁、适应性自旋锁)。

2026-07-06 16:51:32 284

原创 浅谈:编程语言中的那些「锁」事(一)

A 排队在 1 号售票窗,B 排队在 2 号售票窗,两人同时递出身份证买票,好巧不巧,1 和 2 号窗口的售票员同时说这班车只有一张票,怎么办?他说,我这里有一把锁,会放在你们中间的位置上,谁抢到就先给谁买票,这样对 A 和 B 都公平。如果不加锁,高铁票就会被 A 和 B 抢来抢去,变得面目全非,甚至还会出现一开始票价为 50 元,结果抢着抢着可能就被人把价格改到了 100 元。,在编程语言中并不陌生。所以,给高铁票(变量或方法函数)加一个锁,谁抢到锁,就有权使用该高铁票(变量或方法函数),保证其安全。

2026-07-06 09:13:25 227

原创 经典算法实例分析:复写零

而实际上我们可以不需要开辟栈空间来模拟放置元素,我们只需要用两个指针来进行标记栈顶位置和现在需要放置的元素位置即可。我们用 top 来标记栈顶位置,用 i 来标记现在需要放置的元素位置,那么我们找到原数组中对应放置在最后位置的元素位置,然后在数组最后从该位置元素往前来进行模拟放置即可。给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。注意:请不要在超过该数组长度的位置写入元素。请对输入的数组就地进行上述修改,不要从函数返回任何东西。

2026-07-05 09:20:01 169

原创 在长度2N的数组中找出重复N次的元素(二)

记重复 n 次的元素为 x。由于数组 nums 中有 n+1 个不同的元素,而其长度为 2n ,那么数组中剩余的元素均只出现了一次。因此我们可以对数组进行一次遍历,并使用哈希集合存储已经出现过的元素。如果遍历到了哈希集合中的元素,那么返回该元素作为答案。时间复杂度:O(n)。我们只需要对数组 nums 进行一次遍历。空间复杂度:O(n) ,即为哈希集合需要使用的空间。也就是说,我们只需要找到重复出现的元素即为答案。

2026-07-03 16:16:42 179

原创 在长度2N的数组中找出重复N次的元素(一)

【代码】在长度2N的数组中找出重复N次的元素(一)

2026-07-03 08:37:07 220

原创 浅谈:什么是乐观锁CAS

其实因为 AtomicInteger 类也在 rt.jar 包下面的,所以 AtomicInteger 类就是通过 Bootstrap 根类加载器进行加载的, Unsafe 类具体实现就得看 hotspot 源码, unsafe.cpp,C++ 的代码就不在具体在这里分析,感兴趣的同学可以去看看,从代码里可以看到 CAS 的实现离不开处理器的支持,根据当前处理器的类型来决定是否为 cmpxchg 指令添加 lock 前缀。在不使用锁(没有线程被阻塞)的情况下实现多线程之间的变量同步。评论留言少 BUG!

2026-07-02 17:33:11 199

原创 经典算法实例:从根到叶的二进制数之和

例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1 ,那么它表示二进制数 01101 ,也就是 13。给出一棵二叉树,其上每个结点的值都是 0 或 1。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。后序遍历的访问顺序为:左子树——右子树——根节点。如果节点是非叶子节点,返回它的左子树和右子树对应的结果之和。对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。如果节点是叶子节点,返回它对应的数字 val。在二维平面上的 x 轴上,放置着一些方块。

2026-06-29 11:28:23 234

原创 Bagging并行式集成学习

重复步骤 1 到 3 ,构建多棵决策树,最终的结果就和上述 Bagging 的集合结果的方法相似。,表示自助抽样集成,将训练集随机有放回地采样得到m个样本的采样集,基于每个采样集训练一个基学习器,再预测时将它们结合得到结果,通常分类问题使用**投票法**生成结果,回归问题使用**平均法**作为最终的结果。1. 从原始数据集中使用自助采样(bootstrap sampling)的方法随机抽取若干个样本构建新的训练集,即每个训练集都是由原始数据集中采样得到的,每个样本被采样到新的训练集的概率为 n/1。

2026-06-28 11:49:50 241

原创 集成学习算法之提升树(Boosting Tree)

如大家所熟悉的,提升树(Boosting Tree)是一种常见的集成学习算法,它通过逐步迭代的方式训练多个决策树,每一棵树都试图纠正前面树的预测误差,从而得到一个更加准确的整体模型。提升树的基本思路是,每一次训练新的决策树都会关注前面树的误差,让新树尽可能地纠正前面树的错误。在每一次训练中,提升树会根据当前模型的预测结果和真实标签之间的差异,构建一个新的树模型,并将其与前面的模型组合起来形成一个更加准确的模型。这个过程会重复多次,直到模型收敛或达到指定的迭代次数为止。

2026-06-27 16:12:33 348

原创 面试季:这样的简历能让面试官眼前一亮!

因为其它文件格式兼容性不高,可能会使简历模板变形,有些同学在导出时简历格式不正确,那么 HR 在打开你简历的时候可能会出现乱码等尴尬的现象,所以最好输出为 PDF 格式,省心又简洁。一封合格的简历字数大概在 350 词 – 650 词之间,少于 350 词的简历显得空空荡荡,述无可述,容易让人觉得项目经历不足。使用简单的句子和段落来概括你的信息,使得雇主能够快速地了解你的背景和能力。最重要的一点也是容易被忽略的一点,确保简历格式一致,使用同样的字体和大小,并仔细检查拼写和语法错误。

2026-06-27 13:48:35 163

原创 求职经验分享:学会用数据表达与自我“包装”

自己,总结自己的闪光点,能加深面试官的印象,从其他简历中脱颖而出。其实从深层来讲,可以从这一点上看出一个人是否拥有一定的综合能力,这是加分项,其实每个人都有。求职其实就是一个自我推销的过程,简历就是你的文案,将数据可视化不但能让面试官一眼就抓住重点,也方便突出自己的成果。如果是刚毕业的应届生,可以写明参加过哪些比赛且拿过哪些奖项,最好是跟面试相关的,比如 ACM 、黑客马拉松比赛等。如果成绩比较一般:但是做过许多项目,且都拿到了不错的奖项,那也是可以量化的数据。注意:包装并不是造假,没有的东西千万不要写。

2026-06-26 12:18:46 397

原创 经典算法联系专区:复写零(二)

而实际上我们可以不需要开辟栈空间来模拟放置元素,我们只需要用两个指针来进行标记栈顶位置和现在需要放置的元素位置即可。我们用 top 来标记栈顶位置,用 i 来标记现在需要放置的元素位置,那么我们找到原数组中对应放置在最后位置的元素位置,然后在数组最后从该位置元素往前来进行模拟放置即可。时间复杂度:O(n) ,其中 n 为数组 arr 的长度,需要遍历两遍数组。空间复杂度:O(1) ,仅使用常量空间。

2026-06-25 16:16:43 242

原创 经典算法联系专区:复写零(一)

给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。注意:请不要在超过该数组长度的位置写入元素。请对输入的数组就地进行上述修改,不要从函数返回任何东西。

2026-06-25 13:50:52 173

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除