- 博客(293)
- 收藏
- 关注
原创 解题代码清爽版
具体来说就是把我们的解题方法也要放入public class Main {}里,与public static void main(String[] args)并列。我们的方法要加static。因为static方法(静态方法)才可以直接从main中调用。不带static则为实例方法,且不能被直接调用。其实解题代码既不需要创建Solution类,也不需要Scanner读取,直接构造测试用例即可。
2026-09-03 22:36:41
201
原创 LeetCode CodeTop 88.合并两个有序数组
这可以算作一个小优化,比如nums1 = [1,2,3,*,*,*],nums2 = [4,5,6],其实只要把nums2的所有数都填入nums1中,合并就已经结束了,即便此时p1 = 2仍然 >= 0。这里nums1中的6是最大的,应当填入末尾。1.错误思路:如果从左往右地把nums2合并到nums1中,假设nums2[0] < nums1[0],那么nums2[0]会直接覆盖掉nums1[0],这不是我们期望看到的。
2026-06-11 18:35:36
262
原创 LeetCode CodeTop 82.删除排序链表中的重复元素Ⅱ
两个指针分别指向cur.next和cur.next.next,如果发现重复就一次性删除所有值为val的节点;否则cur正常前进一位。(1)时间复杂度:O(n),其中n为链表的长度。(2)空间复杂度:O(1),仅用到若干额外变量。
2026-06-11 16:28:49
276
原创 快手 CodeTop LeetCode 227.基本计算器Ⅱ
操作符栈ops的栈顶元素的优先级比当前遇到的操作符的优先级高或者相等,则while()循环进行eval()操作,即将数字栈nums栈顶的两个元素取出来,然后和操作符栈ops的栈顶操作符进行相应的计算,并将计算结果压回数字栈nums中。eval()函数,用于从数字栈nums中弹出两个数字a和b,再从操作符栈ops中弹出操作符号,进行计算后将结果数字加入到数字栈nums中。设计一个哈希表来存储' + '' - '' * '' / '的优先级,我们将+和-设计为1优先级,将*和/设计为2优先级。
2026-06-03 22:03:54
239
原创 快手 CodeTop LeetCode 224.基本计算器
(3)如果是减号'-',逻辑同加号,将当前的数字累加到结果中,并重置符号为负(下一个数字是负数)。(5)如果是右括号')',遇到右括号,先把括号内的数字和符号计算完毕,然后合并回括号前的现场。(2)如果是加号'+',那么就将当前的数字累加到结果中,并重置符号为正(下一个数字是正数)。(1)如果是数字字符'0' ~ '9',那么就连续读取数字,构建完整的数值。(4)如果是左括号'(',遇到左括号,先保存现场,然后重置符号。(6)别忘了加上最后一个数字。(1)时间复杂度:O(n)。(2)空间复杂度:O(n)。
2026-06-03 20:11:44
247
原创 CodeTop 剑指Offer LCR 143.子结构判断
2.空间复杂度:O(M),当树A和树B都退化为链表时,递归调用的深度最大。一、思路:如果树B是树A的子结构,则子结构的根节点可能为树A的任意一个节点。当树A为空或者树B为空时,直接返回false(根据题意,空树不是任何树的子结构)树B是树A右子树的子结构,对应isSubStructure(A.right,B)树B是树A左子树的子结构,对应isSubStructure(A.left,B)以节点A为根节点的子树包含树B,对应dfs(A,B)函数成立。1.规定树A的根节点记作节点A,树B的根节点记作节点B。
2026-06-02 19:11:43
272
原创 美团 LeetCode 692.前K个高频单词
如果词频相等,根据字典序的大小进行倒序构建,最终确保堆顶元素是堆中“词频最小 & 字典序最大”的元素。词频等于堆顶元素时,根据当前元素与堆顶元素的字典序大小决定(如果字典序大小比堆顶元素要小则入堆)如果词频不相等,根据词频进行升序构建,保证堆顶元素是堆中词频最小的元素。(2)使用最多n个元素维护一个大小为k的堆,复杂度为O(nlogk)。词频大于堆顶元素时:将堆顶元素弹出,并将当前元素添加到堆中。词频小于堆顶元素时:当前元素不可能是前K大的元素,直接丢弃。在优先队列(堆)的基础上,增加了字典序大小的比较。
2026-05-31 19:40:18
277
原创 阿里 LeetCode 1189.“气球“的最大数量
思路:根据题目模拟即可。先统计text中与单词balloon相关的字符数量,由于一个单词需要消耗两个l和o字符,对其统计数量进行除2向下取整,然后所有字符的最小出现次数即是能够凑成balloon的最大数量。1.时间复杂度:假如C为目标字符串的字符种类数量,本题中C = 5,统计text的词频复杂度为O(n),计算答案的复杂度为O(C),因此整体的复杂度为O(n + C)。2.空间复杂度:O(C)。
2026-05-26 16:49:43
58
原创 LeetCode CodeTop 113.路径总和Ⅱ
对于“一条链 + 完全二叉树”这样的“扫帚型”二叉树,我们会在O(n)个叶子节点处,都去复制长为O(n)的path(res.add(new ArrayList<>(path))),所以总的时间复杂度为O(n^2)。5.在递归返回之前,把我们在递归开头加入的节点,也就是当前path的最后一个节点,从path中去掉(恢复现场)。如果不及时去掉的话,会导致最终加到答案中的path,既包含左子树的节点,又包含右子树的节点,这连“路径”都算不上。思路:在递归的同时,额外维护从根到当前节点的元素和sum。
2026-05-08 23:03:24
102
原创 阿里淘天/京东 CodeTop LeetCode103.二叉树的锯齿形层序遍历
(1)时间复杂度:O(n),其中n为二叉树的节点数量,即BFS需要循环n次,占用O(n)。(2)空间复杂度:O(n),最差情况下,即当树为满二叉树时,最多有n/2个树节点同时在deque中,使用O(n)大小的额外空间。否则,添加至tmp头部。(b)当前层循环打印:循环次数为当前层的节点数(即deque的长度)。(2)初始化:打印结果空列表res,包含根节点的双端队列deque。——添加子节点:若node的左(右)子节点不为空,则加入deque。(1)特例处理:当树的根节点为空时,直接返回空列表[]。
2026-05-07 22:32:57
97
原创 字节/蚂蚁/美团/拼多多 CodeTop LeetCode 165.比较版本号
version1 的第二个修订号为 "2",version2 的第二个修订号为 "10":2 < 10,所以 version1 < version2。2.查看下面的示例:发现示例1的列表为[1,2]和[1,10],示例2的列表均为[1,1],示例3的列表均为[1,0,0,0]。(1)时间复杂度:O(n + m),其中n是version1的长度,m是version2的长度。忽略前导零,"01" 和 "001" 都代表相同的整数 "1"。(2)如果a[i] < b[i],返回-1;(4)否则继续向后遍历;
2026-05-07 20:55:54
99
原创 快手/字节 CodeTop LeetCode 415.字符串相加
3.索引溢出处理:当指针i或j走过数字首部后,给n1、n2赋值为0,相当于给num1、num2中长度较短的数字前面填0,以便后续计算;2.添加当前位:计算tmp = n1 + n2 + carry,并将当前位tmp % 10,添加至res头部;4.当遍历完num1、num2后,跳出循环,并根据carry值决定是否在头部添加进位1,最终返回res即可。1.时间复杂度:O(max(M,N)),其中M和N为两个数字的长度,按位遍历一遍数字(以较长的数字为准)。思路:模拟人工加法。
2026-05-07 18:58:18
93
原创 字节 LeetCode CodeTop 912.排序数组
如果子数组是降序的,且我们每次都选子数组的第一个(或者最后一个)元素作为pivot,那么按照算法,j不变或者移动到最左边,划分是最不均匀的,算法会退化至O(n^2)。递归深度为O(logn),每一层都会涉及O(n)个元素的比较和交换,所以时间复杂度等于一个高为O(logn),底边长为O(n)的矩形的面积,即O(nlogn)。(b)如果写成i <= j,那么最终i = 2,j = 1。这个做法会在子数组所有元素相同时,划分后的j是子数组的最后一个元素的下标,是最不均匀的划分,算法也会退化至O(n^2)。
2026-05-07 15:32:23
224
原创 阿里 生产者-消费者模式
(3)缓冲区:临时存储数据的容器(通常用队列实现),解耦生产者和消费者。(1)生产者:负责生成数据/任务,将其放入共享缓冲区。├─ notifyAll()(消费者还在睡眠,无影响)├─ Producer 生产 1 → 队列: [1]├─ 队列为空,生产 2 → 队列: [2]├─ 队列有 2,消费 2 → 队列: [](3)操作完成后,notifyAll()。├─ 队列非空,消费 1 → 队列: [](1)队列满时,生产者wait()。(2)队列空时,消费者wait()。
2026-05-06 20:53:47
250
原创 美团 手撕策略模式
具体策略(Concrete Strategy):实现策略接口,封装具体的算法或行为。避免多重条件判断:消除了大量的if-else或switch-case。策略接口(Strategy):定义所有策略类必须实现的公共接口。上下文(Context):持有策略对象的引用,负责调用策略。(2)客户端需要了解不同策略的区别,选择合适的策略。策略模式让算法的变化独立于使用算法的客户。运行时切换:可以在运行时动态改变对象的行为。1.定义:策略模式是一种行为设计模式,它。(1)系统有多种处理方式,需要动态选择。
2026-05-05 20:41:35
62
原创 阿里 约瑟夫环问题
题目要求:实现一个约瑟夫环(Josephus problem):N个人围成一圈,从第一个人开始按顺序报数,每数到第M个人就把他淘汰(出局),然后从下一个人重新报数。(1)时间复杂度:O(n × m),需要淘汰n - 1个人,每淘汰一个人都要检查m个元素,当n较大时效率低。(1)假设已知n - 1个人的时候,幸存者索引为f(n - 1),它是在旧圈中的位置。(2)当人数从n - 1增加到n时,相当于在圆圈中插入了一个新的人(编号0)。从1数,2出局,剩下:1,3,4,5(从3开始)
2026-05-05 12:38:55
232
原创 快手/腾讯 CodeTop LeetCode 43.字符串相乘
对于num1[i]×num2[j],其结果一定为1-2位,且第一位(前一位)位于res[i + j],第二位(后一位)位于res[i + j + 1]如果乘数num1的位数为m,乘数num2的位数为n,那么num1 × num2的结果res的最大总位数为m + n。(1)时间复杂度:O(m * n),其中m和n分别为两个字符串的长度。(2)空间复杂度:O(m + n),存储结果数组。思路:乘法的竖式运算。
2026-05-04 16:57:00
77
原创 LeetCode 18.四数之和
如果i > 0且nums[i] = nums[i - 1],那么nums[i]和后面数字相加的结果,必然在之前算出过,所以无需执行后续代码,直接continue外层循环(可以放在循环开头判断)如果j > i + 1且nums[j] = nums[j - 1],那么nums[b]和后面数字相加的结果,必然在之前算出过,所以无需执行后续代码,直接continue(可以放在循环开头判断)注意这里的j > i + 1的判断是必须的,如果不判断,对于示例2这样的数据,会直接continue,漏掉符合要求的答案。
2026-05-04 12:08:11
349
原创 剑指Offer 60.n个骰子的点数
(1)因此dp[i][j] = dp[i - 1][j - 6] + dp[i - 1][[j - 5] + dp[i - 1][j - 4] + dp[i - 1][j - 3] + dp[i - 1][j - 2] + dp[i - 1][j - 1]。因此所有的总和值构成了一个连续的整数区间。(2)即:dp[i][j] = dp[i - 1][j - k] for k = 1 to 6。1.确定dp数组及其下标的含义:dp[i][j]表示投掷i个骰子,点数总和恰好等于j的概率。
2026-05-03 21:51:41
90
原创 LeetCode 378.有序矩阵中第K小的元素
虽在在过程中ans记录的可能不是矩阵中的元素,但由于我们不断缩小范围,最终会下降到矩阵中实际存在的元素,这是因为:任何不在矩阵中的元素x,如果它满足小于等于它的数cnt >= k,那么比它小的下一个矩阵元素也一定满足cnt >= k。(2)闭区间右端点的初始值:matrix[n - 1][n - 1],有n^2个数 <= matrix[n - 1][n - 1],由于n^2 >= k,所以一定满足要求。2.在本题中是找第k小的元素,因此就是找最小的x,满足 <= x的数至少有k个。据此,可以二分猜答案。
2026-05-03 20:19:12
283
原创 字节 设置一个带超时时间的LRU缓存
(1)在定义双向链表节点Node的时候,给Node增加过期时间戳字段expireTime(表示该节点的过期时间是多少)和检查节点是否过期的成员方法(实例方法)boolean isExpired()(如果当前时间的毫秒数System.currentTimeMillis() > expireTime,那么就return true,表示该节点已经过期)。1.思路:需要在LRU的基础上继续实现。
2026-05-03 16:31:17
195
原创 n个六面的骰子,扔一次之后和为k的概率是多少?
(1)因此dp[i][j] = dp[i - 1][j - 6] + dp[i - 1][[j - 5] + dp[i - 1][j - 4] + dp[i - 1][j - 3] + dp[i - 1][j - 2] + dp[i - 1][j - 1]。有n个组(每组对应一个骰子),每组有6个物品(点数1~6),每组必须且只能选1个物品,求恰好凑成总重量k的方案数。每个骰子的点数都是1~6,因此n个骰子的总点数和的范围是[n,6n],需要计算点数之和恰好等于k的方案数。思路:动态规划dp。
2026-05-03 15:26:12
96
原创 CodeTop LeetCode 7.整数反转
但是将1147483649这个数字反转过来后就变成了9463847411,这就比最大的32位整数还要大了,这样的数字是没法存到int里面的,所以肯定要返回0(溢出了)。(a)在下图中,绿色的是最大的32位整数,第二排数字中,橘色的是5,是大于原数字原位置的4的,这就意味着5后面跟任何数字,都会比Integer.MAX_VALUE大。举例:以12345为例,先拿到5,再拿到4,之后拿到3,2,1,我们按这样的顺序就可以反向拼接出一个数字了,也就是能达到反转的效果。这两种方法是可以的,但并不好。
2026-05-03 13:37:57
351
原创 字节高频题 小于n的最大数
在从左到右的选择过程中,一旦在某个位置选择了小于n对应位的数字,后面所有位的数字都要取允许集合中的最大值,这样求得的结果就一定是在该前缀下的最大的。过程:第一位要找 <= 3的最大允许数字 -> 最大是2,并且2 < 3,所以第一位直接选2,后面直接全部选允许集合中的最大值, 得到299 < 333,成功。(3)如果没有办法构造一个和n的位数相同、但值小于n的数字,那么就退一步,构造一个比n少一位,且每一位都取允许集合中的最大数字的数。(1)示例1:n = 333,允许数字 = {2,5,9}。
2026-05-02 17:33:24
293
原创 LeetCode CodeTop 92.反转链表Ⅱ
1.思路:找到要反转区间的前一个位置preLeftNode和它的下一个节点LeftNode,然后对待反转区间的元素进行反转,然后重新连接链表。preLeftNode去连反转链表的新头节点,反转区间的最后一个节点LeftNode去连反转区间后的第一个节点。(1)时间复杂度:O(right)。(2)空间复杂度:O(1)。
2026-05-02 14:05:47
102
原创 LeetCode CodeTop 162.寻找峰值
(如果不满足,那么一定有nums[i + 1] < nums[i + 2],nums[i + 2] < nums[i + 3],...,nums[n - 1] < nums[n] = -∞,可知不成立,因此在下标[i + 1,n - 1]中一定存在峰值)。题目规定了nums[-1] = nums[n] = -∞,也就是假设nums[0]的左边还有一个-∞,nums[n - 1]的右边还有一个-∞。如果数组是严格递增的,那么nums[n - 1]就是(唯一的)峰值。(2)空间复杂度:O(1)。
2026-05-02 11:53:32
123
原创 LeetCode CodeTop 143.重排链表
1.题目要求:将原链表重排序为:第一个节点->最后一个节点->第二个节点->倒数第二个节点->第三个节点->倒数第三个节点...。2.思路:以1->2->3->4->5为例。(1)找到链表的中间节点middleNode:快慢指针法,找到中间节点mid = 3。(2)翻转后半部分的链表reverseList:从中点开始反转后半部分的链表。反转后:1->2->3,5->4->3(注意3是共享节点)。(3)交错合并:两个链表的节点从前往后逐个交错合并。3.复杂度分析:(1)时间复杂度:O(n),其中n为链表的长度
2026-05-01 20:30:09
371
原创 腾讯 CodeTop LeetCode 470.用Rand7()实现Rand10()
目标应该是1~10每个数的概率都为1/10,结果1,2,4,5,7,8,10的概率为1/7,3,6,9的概率为0,不合题意。1.前提:rand7()可以均匀生成1,2,3,4,5,6,7,目标是rand10()均匀生成1 ~ 10。(1)令a = rand7() - 1,取值:0,1,2,3,4,5,6(均匀)。(2)令b = rand7(),取值:1,2,3,4,5,6,7(均匀)。rand7()取值:1,2,3,4,5,6,7。除以7:1,2,4,5,7,8,10。映射到 1~49,这是一个。
2026-04-30 21:20:10
227
原创 不均匀硬币模拟均匀硬币
题目要求:有一个rand函数,生成1的概率是p,0的概率是1 - p,那么如何用它生成一个rand2(),使得生成1和0的概率都是0.5。本质上是用不均匀硬币模拟均匀硬币。1.思路:连续抛两次不均匀硬币,结果有四种可能,分别是01,10,00,11。所以,可以遇到01就输出0,遇到10就输出1,遇到00或11就重新抛。(2)如果a == 1 && b == 0,就返回1。(3)如果a == 0 && b == 1,就返回0。(1)调用两次rand(),生成随机的(a,b)。(4)否则重复步骤(1)。
2026-04-30 16:33:26
60
原创 给定一个数组,用最小的比较次数获得最大最小值
1.思考:如果分别独立找max和min,需要2n - 2次比较。考虑采用分组成对法,在⌊3n/2⌋ - 2次比较内完成。3.优化点:每两个数只需要三次比较(组内比1次 + 更新最大值1次 + 更新最小值1次),而不是4次。(2)如果数组长度n为奇数的话:最后一个元素单独处理,与当前的max/min比较(两次额外比较)。(1)如果数组长度n = 1的话:min = max = 该数,只需0次比较。(2)每组内先比较两个数,分出较大和较小。(4)用当前较小值与全局最小值比较。(1)将数组元素两两分组。
2026-04-30 15:25:38
76
原创 手撕归并排序
(2)空间复杂度:O(n)(需要额外数组存储排序结果)。归并排序是否稳定:稳定,合并时会保持相等的元素顺序。时间复杂度:始终为O(nlogn),无论好坏。(4)特点:数据不敏感,可轻松用于链表排序。合并:将两个有序子数组合并成一个有序数组。(1)分治策略 + 合并有序数组。递归:对左右两半分别归并排序。分解:将数组从中间分成两半。将数组不断对半分成子数组。排序后合并有序子数组。
2026-04-30 14:28:23
58
原创 手撕快速排序
最坏情况下的时间复杂度(数组已经正序或逆序排序,并且基准元素选择的是队首或队尾):O(n^2)选择一个基准元素(pivot),将数组分成两部分:左边部分 <= 基准;右边部分 >= 基准。分区(partition):通过交换将元素放到基准两侧。(2)空间复杂度:O(logn)(递归栈)。(3)递归地对左右两部分进行同样的操作。(a)平均时间复杂度:O(nlogn)。最好情况下的时间复杂度:O(nlogn)选择基准(如第一个、最后一个、或随机)(1)分治策略 + 原地排序。实际应用中通常比归并排序快。
2026-04-30 12:42:45
107
1
原创 百度/快手 手撕单例模式
确保一个类在程序的整个生命周期中,有且只有一个实例,并提供一个全局访问点来获取这个实例。多个模块需要共享同一个资源,或者创建某个对象的成本很高的时候,适合使用单例模式。提供一个公开的静态方法:作为全局访问点,让外部获取这个内部持有的唯一实例。二、饿汉式:在类加载时就完成实例的创建,是线程安全的。二、饿汉式:在类加载时就完成实例的创建,是线程安全的。:全局共享一个连接池对象,复用数据库连接,节省资源。提供一个静态变量:在类的内部持有自己唯一的实例。在类加载时就完成实例的创建,是线程安全的。
2026-04-29 21:01:32
105
原创 阿里 两个线程循环打印奇偶数
一、方法一:Synchronized + wait/notify。一、方法一:Synchronized + wait/notify。二、方法二:ReentrantLock + Condition。二、方法二:ReentrantLock + Condition。三、方法三:使用信号量 Semaphore(最简洁)三、方法三:使用信号量 Semaphore(最简洁)题目要求:两个线程循环打印奇偶数。
2026-04-29 18:52:46
95
原创 hot100 287.寻找重复数
4.考察包含节点0的连通块,其形状和142.环形链表Ⅱ是一样的,所以都可以用快慢指针解决,这两题的联系如下表所示,注意i和nums[i]都是节点。(2)由于nums[i] >= 1,所以节点0的入度是0,不在环上。从节点0出发,进入基环,基环的入环口,就是入度大于1的节点。(1)在每个节点的出度都是1的情况下,n + 1个点n + 1条边的有向图,又叫内向基环森林,每个连通块都恰好有一个环。(2)对于i = 0,1,2,..,n,连接一条从i到nums[i]的有向边,可以得到一个有向图。
2026-03-08 17:50:00
85
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅