自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 287. 寻找重复数

中等给定一个包含n + 1个整数的数组nums,其数字都在[1, n]范围内(包括1和n),可知至少存在一个重复的整数。假设nums只有,返回。你设计的解决方案必须数组nums且只用常量级O(1)的额外空间。

2026-03-19 22:34:37 546

原创 31. 下一个排列

31. 下一个排列中等整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。给你一个整数数组 ,找出 的下一个排列。必须原地修改,只允许使用额外常数空间。示例 1:示例 2:示例 3:提示:题意描

2026-03-19 22:33:48 774

原创 75. 颜色分类

千层饼刷漆法:默认先把当前位置刷成蓝色 (2);如果发现是白色或红色,就往前回溯刷一层白色 (1);如果发现是红色,再往更前回溯刷一层红色 (0)。逻辑:所有的 0 肯定在 1 前面,所有的 1 肯定在 2 前面。操作遇到任何数:先填 2。p1指针处填 1,p1前移。p0指针处填 0,p0前移。关键p1总是走在p0前面(或重合),覆盖顺序保证了 0 不会覆盖 1,1 不会覆盖 2(在错误的位置)。

2026-03-18 22:44:57 429

原创 169. 多数元素

极限一换一:不同的数字见面就‘同归于尽’,相同的数字见面就‘抱团取暖’。因为众数超过了总数的一半,所以哪怕它跟所有其他异类一个个对掉,最后活下来的肯定还是它。物理意义:把数组看作战场。ans是当前的擂主,hp是他的兵力。抵消机制:遇到同盟(x == ans),兵力 +1;遇到敌人(x!= ans),兵力 -1(相当于和一个敌人同归于尽)。换人机制:当兵力耗尽(hp == 0)时,说明之前的擂主已经拼光了,当前的x顺势成为新擂主。

2026-03-18 22:44:24 433

原创 136. 只出现一次的数字

消消乐魔法:异或运算就像‘对对碰’,两个相同的数字相遇会变成 0(相互抵消),最后剩下的那个就是落单的数字。性质 AN ^ N = 0(自己异或自己,归零)。性质 BN ^ 0 = N(任何数异或 0,保持不变)。性质 C:满足交换律和结合律 (顺序无所谓,a ^ b ^ c等于a ^ c ^ b结论0 ^ 0 ^ cc。

2026-03-16 22:29:12 338 1

原创 72. 编辑距离

改作业游戏:把单词 A 改成单词 B,每次只能动一个字母。如果当前字母不一样,我有三张牌可以出——‘删除’、‘插入’、‘替换’,看哪张牌能让我用最少的步数通关。状态定义dfs(i, j)表示将s[0...i]变成t[0...j]所需的最少操作次数。决策逻辑相等:直接跳过,不做操作 (不等:尝试三种操作,取最小值min(删, 插, 改) + 1。“进化论表格:从‘空串’进化到‘完整串’,每一步都可以选择‘删’(继承上面)、‘插’(继承左边)或‘改’(继承左上角),我们要选代价最小的那条路。状态定义。

2026-03-16 22:28:40 567

原创 1143. 最长公共子序列

消消乐游戏:从后往前比,如果两个字符一样,就都消掉并在得分本上 +1;如果不一样,就分别试着保留其中一个,看谁剩下的潜力大。状态定义dfs(i, j)表示s[0...i]和t[0...j]的最长公共子序列长度。决策逻辑相等 (:这是“白给”的公共字符,必须选!结果是。不等 (s[i]!= t[j]:要么s[i]没用,要么t[j]没用。我们看看删掉s[i]) 和删掉t[j]) 哪条路结果更好。

2026-03-15 21:10:12 444

原创 5. 最长回文子串

投石问路:以每一个可能的中心点(单个字符或两个字符的间隙)为圆心,向两边同时扩散,直到碰到不一样的字符为止。回文特性:中心对称。中心点:对于长度为 的字符串,共有 个中心( 个单字符中心, 个双字符间隙中心)。策略:枚举所有中心,向外while循环扩散。“万物皆中心:不管是字符还是间隙,我都给它一个编号i。通过除法把编号还原成左右指针,一次循环搞定所有奇偶情况。总中心数:长度为 的字符串,有 个中心点。映射公式l = i / 2当i是偶数时,l == r(指向同一个字符,奇回文当i。

2026-03-15 21:09:37 537

原创 64. 最小路径和

比价游戏:想要到达当前格子(i, j)的花费最少,就得问问它的前一步——‘上面’和‘左面’哪个更便宜,选便宜的那个加上我自己的值。状态定义dfs(i, j)表示从起点(0, 0)到达(i, j)的最小路径和。转移方程dfs(i, j) = min(dfs(上), dfs(左)) + grid[i][j]。边界处理:越界的地方视为“无穷大代价”,这样Math.min永远不会选择越界的路。

2026-03-13 21:30:36 509

原创 62. 不同路径

溯源游戏:我想知道走到终点(i, j)有几条路,就问问它的‘上家’——它头顶的格子(i-1, j)和左边的格子(i, j-1)各有几条路。状态定义dfs(i, j)表示从起点(0, 0)走到(i, j)的路径总数。转移方程dfs(i, j) = dfs(上) + dfs(左)。加法原理:路径总数等于所有可能的来源之和。“网格填数:每一个格子的路径数,都等于它‘正上方格子’和‘正左方格子’的路径数之和(汇流原理)。状态定义对应实际网格(i, j)的路径数。转移方程。哨兵技巧是唯一的“火种”。

2026-03-13 21:30:05 494

原创 32. 最长有效括号

栈底坐镇一个哨兵(红线),栈里存左括号下标(炸弹)。遇到右括号就尝试消掉一个炸弹,计算距离;消不掉就说明断连了,重置红线。栈内存放:下标 (Indices)。栈底含义“最后一个没有被匹配的右括号的下标”。它是计算长度的基准线。计算公式:当前右括号下标i- 栈顶下标(因为栈顶就是这一段有效括号的“起跑线前一位”)。

2026-03-12 23:58:52 624

原创 416. 分割等和子集

0/1 背包问题:把这一堆数字看作物品,能不能从中挑出一些物品,刚好填满容量为的背包?转化:只要找到一个子集和等于总和的一半,剩下的元素和自然也是一半。状态dfs(i, j)询问“在前i个物品中,能不能凑出和为j?选择:对于每个数字nums[i],只有两种选择——选它或者不选它。“填表游戏:我们有一排格子(容量 0 到 Target),每一个新来的数字都试图去勾选新的格子——要么继承上一行的结果,要么在上一行已有的结果上加上自己。状态定义f[i][j]表示“在前i个数字中,能否凑出和为j转移方程。

2026-03-12 23:58:21 393

原创 152. 乘积最大子数组

双面间谍策略:同时维护‘最大值’和‘最小值’,因为当前的‘最小值’(负数)乘以一个负数,可能立马翻身变成‘最大值’。状态定义fMax:以当前位置结尾的最大乘积。fMin:以当前位置结尾的最小乘积(为了等待下一个负数来实现逆袭)。转移方程:由于负数的存在,最大值可能来自:fMax * x(正数 正数)fMin * x(负数 负数 变成大正数)x本身(前面的积累太烂了,不如从头开始,相当于 Kadane 中的 restart)。

2026-03-11 20:53:54 552

原创 300. 最长递增子序列

接龙游戏:每一个数字都回头看,找出比自己小的‘前驱’中尾巴最长的那一个,接在它后面。状态定义dfs(i)表示以nums[i]结尾的最长递增子序列的长度。转移逻辑:遍历j < i。如果,说明i可以接在j后面。我们想要。结果:答案不仅仅是dfs(n-1),而是所有位置中的最大值。“接龙比赛:轮到我(第i个)接龙时,我回头看所有比我小的队友(j),挑一个最长的队伍接在后面。状态定义f[i]表示以nums[i]结尾的最长递增子序列的长度。状态转移,其中0 <= j < i且。

2026-03-11 20:53:22 589

原创 139. 单词拆分

中等给你一个字符串s和一个字符串列表wordDict作为字典。如果可以利用字典中出现的一个或多个单词拼接出s则返回true。不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。wordDict。

2026-03-10 23:40:45 418

原创 322. 零钱兑换

无限续杯策略:面对一种面额的硬币,我有两个选择——要么‘完全不选’它(去看不选它的情况),要么‘选’它一枚,然后赖在这里不走,看看能不能‘再选’一枚。模型:完全背包。硬币数量无限。状态dfs(i, c)表示用前i种硬币凑出金额c的最小数量。防溢出技巧:使用作为无穷大。这样即使+1也就是变成一个稍微大一点的整数,绝对不会溢出成负数。“抄作业逻辑:要想凑出金额c,要么完全照抄‘上一行’(不选这枚硬币),要么在‘这一行’里找前一个状态加 1(选这枚硬币,且允许重复选)。状态定义f[i+1][c]

2026-03-10 23:40:05 410

原创 279. 完全平方数

找零钱问题:把看作不同面额的硬币,目标是凑出总额n,问最少需要几枚硬币?模型:完全背包(Unbounded Knapsack)。区别:0/1 背包选了就得跳到i-1,而这里选了当前平方数,还可以继续留在i再选一次(例如Static 技巧:题目会多次调用numSquares,利用static缓存,计算过的结果(比如)在下一个测试用例里可以直接用。“一次算好,终身受用:把所有 1 到 10000 的答案提前算好填在表格里。填表时,每个完全平方数都可以被‘无限次’使用,这正是完全背包的特征。

2026-03-09 21:47:06 666

原创 198. 打家劫舍

非此即彼的抉择:对于当前的房子i,如果我偷了它,就不能碰隔壁i-1(只能拿i-2的钱);如果我不偷它,那我就可以心安理得地拿走截止到i-1的最大收益。状态定义dfs(i)表示从第 0 间到第i间房子能偷到的最大金额。转移方程。核心约束:相邻的房子不能同时偷,所以选了nums[i]必须跳回到i-2。“滚雪球游戏:走到每一栋房子面前,我手里都攥着两个数据——‘昨天的最大收益’和‘前天的最大收益’。今天的最大收益 = max(昨天不偷, 前天 + 今天偷)。状态定义f[i+2]表示考虑前i+1间房子(即。

2026-03-09 21:46:29 465

原创 118. 杨辉三角

巨人肩膀:每一行的首尾都是 1,中间的每一个数字,都等于上一行‘左肩膀’和‘右肩膀’两个数字之和。性质。边界:第i行有i+1个元素(索引从 0 开始),第 0 个和第i个(最后一个)永远是 1。

2026-03-07 22:48:54 513

原创 70. 爬楼梯

逆向溯源:要想站上第n级台阶,最后一步只能是从n-1迈一步上来,或者从n-2迈两步上来。所以我到n的方法数,就是那两级台阶方法数之和。状态定义dfs(i)表示到达第i级台阶的方法总数。转移方程。这就是典型的斐波那契数列。记忆化:如果没有memo数组,这棵递归树会指数级膨胀;有了memo,这就变成了线性的 $O(N)$。“步步为营:不用操心未来,只看脚下。站在第i级台阶上回顾,我只能是从第i-1级迈一步上来,或者从第i-2级蹦两步上来,没有第三种可能。状态定义f[i]表示到达第i级台阶的方法数。

2026-03-07 22:48:19 493

原创 763. 划分字母区间

橡皮筋扩容法:先用雷达扫描一遍记录每个字母的‘最终归宿’;然后再走一遍,遇到谁就把当前区间的边界‘撑’大到它的归宿位置,直到走到边界为止,咔嚓一刀。预处理:必须先知道每个字母最后出现在哪 (last[]贪心扩充:遍历字符时,当前片段的结束点end必须能够覆盖当前字符的last位置。切割时机:当遍历指针i追上了扩充后的边界end,说明当前片段里的所有字符都已处理完毕,可以安全切割。

2026-03-06 22:22:08 400

原创 45. 跳跃游戏 II

造桥铺路:我在当前这座桥上走的时候(0到curRight),不断计算下一座桥最远能造到哪里(nextRight当我走到当前桥的尽头时,必须启用下一座桥,步数 +1。curRight当前步数能到达的最远右边界(本回合的终点)。nextRight多跳一步能到达的最远右边界(下一回合的潜力)。策略:在到达curRight之前,只记录潜力不跳跃;一旦到达curRight,结算步数,并把潜力兑现为新的边界。

2026-03-06 22:21:36 436

原创 55. 跳跃游戏

只管覆盖范围,不管具体怎么跳。这是一个典型的贪心 (Greedy)问题。我们不需要通过 DFS/BFS 去模拟每一条路径,只需要维护一个变量mx(Max Reach),代表**“当前能量最远能覆盖到的位置”**。只要当前格子i在覆盖范围内 (i <= mx),如果不小心断档了 (i > mx),说明前面跳不到这儿,游戏结束。既然能走到i,那就看看从i起跳能不能把覆盖范围撑得更远。💡数组里的每个数字就是路由器的信号强度。就是该路由器能覆盖到的最远坐标。

2026-03-05 17:15:59 602

原创 121. 买卖股票的最佳时机

历史最低价就是我的买入价,当前价格就是我的卖出价。我们假设自己有一台时光机,遍历到第i在第i天之前(包括第i天),最低的价格是多少?如果我在那个最低点买入,在今天卖出,能赚多少?记录下这个差价,如果比之前的最大利润还大,就更新。💡想象你在画股价走势图。更新谷底(minPrice)。计算落差(当前点 - 谷底),看看是不是最大的瀑布。

2026-03-05 17:15:29 382

原创 295. 数据流的中位数

左边保存小半边(最大堆),右边保存大半边(最小堆),中位数就在山顶上。左半部 (left:存较小的数,用大顶堆(堆顶是这半边最大的,也就是靠近中间的)。右半部 (right:存较大的数,用小顶堆(堆顶是这半边最小的,也是靠近中间的)。💡想象一个沙漏,中间最细的地方就是中位数。上面是右堆(小顶堆),下面是左堆(大顶堆)。我们维持两个堆的平衡:左堆的大小要么等于右堆,要么比右堆多 1 个。

2026-03-04 21:58:24 495

原创 347. 前 K 个高频元素

频率就是下标:出现几次,就扔进第几号桶里。普通排序:比较数值大小。桶排序:把“频率”映射为数组的下标。因为频率不可能超过数组总长度N,所以我们可以直接开一个长度为N+1的数组,下标i存放“出现了i次的所有数字”。取结果:从数组最后(最高频)往前倒着拿,拿到k个就收工。

2026-03-04 21:57:53 655

原创 215. 数组中的第K个最大元素

减治法 (Decrease & Conquer):每次切分后,只去可能有答案的那半边继续切。快速排序:切分完左右两边都要排,复杂度。快速选择:切分完算出基准值的下标j,比较j和target如果:找到了!直接返回。如果j < target:答案在右边,扔掉左边,递归右边。如果j > target:答案在左边,扔掉右边,递归左边。每次扔掉约一半数据,复杂度收敛于 $N + N/2 + N/4... = 2N \approx O(N)$。

2026-03-03 20:49:33 469

原创 84. 柱状图中最大的矩形

寻找左右两边第一个比我矮的柱子,被夹在中间的就是我的最大宽度。对于每一根柱子i,如果以它的高度heights[i]作为矩形的高度,那么这个矩形能向左右延伸多远?向左:延伸到第一个比它矮的下标left。向右:延伸到第一个比它矮的下标right。面积。单调递增栈刚好能帮你找到这两个边界。

2026-03-03 20:48:58 465

原创 739. 每日温度

维护一个‘递减’的等待名单,谁热谁就来清算。我们维护一个栈,栈里存的是还没有找到更高温度的日子的下标。栈里的温度始终保持单调递减(例如一旦遇到一个新的温度比栈顶高,说明栈顶那一天终于等到了“更暖和的日子”,赶紧把它弹出来结算 (i - j。

2026-03-02 23:49:14 447

原创 394. 字符串解码

遇到字母直接拿,遇到数字找配对,拆解成 [重复内容] + [后缀]。我们将字符串看作是一个数学表达式。基本情况:如果是字母,直接保留,处理下一个字符。复杂情况:如果是数字,说明后面跟着一个k[...]的结构。我们需要找到这个结构匹配的右括号,将其拆解为三部分:次数k。内容t:括号里面的部分(需递归解码)。后缀:右括号后面的剩余部分(需递归解码)。

2026-03-02 23:48:43 687 1

原创 155. 最小栈

每个元素入栈时,都背着当时的‘历史最低价’。普通栈只存当前值,最小栈存的是一个元组 (当前值, 入栈时的最小值)。这样,栈顶永远保留着“当前这一刻”的全局最小值。一旦出栈,不仅当前值走了,对应的“最小值状态”也随之撤销,自动回滚到上一个状态。

2026-03-01 17:13:12 625

原创 20. 有效的括号

洋葱剥皮法:最里面的先解决,存什么吐什么。括号匹配必须遵循“后进先出” (LIFO) 的原则,这正是栈 (Stack)的拿手好戏。入栈:遇到左括号,把“未来期待的右括号”压入栈中。出栈:遇到右括号,看看栈顶是不是自己(是不是预期的那个)。💡遇到,就在心里默默记下:“等会儿得来个才能消掉”。遇到,在心里压上:“等会儿得来个只要来了一个右括号,就看能不能和心里记得最清楚(栈顶)的那个对上号。

2026-03-01 17:12:42 556

原创 4. 寻找两个正序数组的中位数

把两个数组切一刀,左边的最大值右边的最小值。中位数的本质就是把所有数字分成等长的两堆:左半部分 和 右半部分。如果总数是偶数:中位数是(Max(左) + Min(右)) / 2。如果总数是奇数:中位数是Max(左)(假设左边多放了一个)。

2026-02-27 22:08:09 793

原创 153. 寻找旋转排序数组中的最小值

盯着最后一个数:比它小的在右边(包含最小值),比它大的在左边。旋转数组就像一个断崖。我们以最后一个元素nums[n-1]左半区 (蓝色):所有数值都。右半区 (红色):所有数值都(最小值就在这半区的第一个位置)。我们的目标就是找到“右半区 (红色)” 的起始点。

2026-02-27 22:07:19 613

原创 33. 搜索旋转排序数组

先看在不在同一侧,再做普通二分。旋转数组本质上是两段有序区间。我们把数组分为 “左半区 (第一段)” 和 “右半区 (第二段)”。参照物是最后一个元素 last。左半区:所有数都> last。右半区:所有数都<= last。我们只需要判断mid和target异侧:如果它俩一个在左半区,一个在右半区,那答案方向是确定的(跨越断崖)。同侧:如果它俩在同一段里,那就退化成了普通的有序数组二分(比较大小即可)。

2026-02-26 23:24:01 384

原创 34. 在排序数组中查找元素的第一个和最后一个位置

找开头是找它自己,找结尾是找它的‘下一位’然后退一步。我们不需要专门写一个 upperBound 或者 findLast。Start: 找 的第一个位置。End: 找 的第一个位置,然后-1。💡,找8。左夹子-> 落在第一个8(下标 3)。右夹子-> 落在10(下标 5)。答案:左夹子不动,右夹子往回缩一格 ->[3, 4]。

2026-02-26 23:22:58 470

原创 74. 搜索二维矩阵

降维打击:把它当成一个长长的有序数组。虽然输入是二维的,但因为题目保证了“每行有序”且“下一行比上一行大”,所以逻辑上它就是一个长度为 $m \times n$ 的一维有序数组。我们只需要搞定 一维下标 (mid) 到 二维坐标 (row, col) 的数学映射即可。💡 坐标映射公式:行号 (Row)mid / n(商:表示跨越了几整行)列号 (Col)mid % n(余:表示在当前行的偏移量)“站在右上角,把矩阵当成一颗二叉搜索树 (BST)。为什么选右上角?向左看:数字变小。

2026-02-25 23:33:23 983

原创 35. 搜索插入位置

寻找第一个大于等于 Target 的位置。lowerBound 的定义是:在一个有序数组中,找到第一个满足 nums[i] >= target 的下标 i。如果target存在,它返回第一个target的下标。如果target不存在,它返回target应当插入的位置(保持数组有序)。

2026-02-25 23:32:52 685 1

原创 51. N 皇后

一行只放一个,三个数组定生死。我们按行 (r) 递归,每一行只在一个位置放皇后。为了快速判断某个位置 (r, c) 是否安全,我们需要三个“记事本”(布尔数组)来记录哪些列、哪些主对角线、哪些副对角线已经被占用了。

2026-02-24 20:55:35 631

原创 131. 分割回文串

手拿菜刀走到底:每个字符后面,切一刀还是连着走?不切 (Join):当前子串还没结束,继续往后看下一位。切 (Cut):当前子串[start, i]结束。前提是:切下来的这段必须是回文串。💡你有一根香肠aab。走到第一个a后面:不切:等着凑个更大的(比如aa切:切下来一块a(它是回文,合法),然后处理剩下那截。

2026-02-24 20:54:31 655

空空如也

空空如也

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

TA关注的人

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