- 博客(141)
- 收藏
- 关注
原创 背包问题-各种背包问题
01背包是基础,倒序是为了不重复拿。完全背包最简单,正序就是为了重复拿。多重背包看需求,求最值拆成01,求方案当做分组。分组背包最讲究,组 -> 容(倒) -> 物,顺序千万别搞错。
2025-12-11 14:00:52
708
原创 形成目标数组的最少操作次数-差分思想
这道题的差分法思路,本质是将“区间操作的次数”转化为“元素高度变化的增量之和”。通过关注相邻元素的差值,我们避开了复杂的区间选择问题,只需要累加所有“上升”的部分——因为“下降”的部分可以被之前的操作自然覆盖。这种将问题“降维”到差值分析的思路,是差分法在区间操作类问题中的典型应用,值得深入理解和借鉴。
2025-10-30 11:36:23
562
原创 删除最短的子数组使数组有序
给定一个整数数组arr,请你删除一个连续子数组(可以为空),使得剩下的元素是非递减的。请返回满足要求的最短子数组长度。先看几个示例,直观感受问题:示例1:3解释:删除[10,4,2],剩余非递减。示例2:4解释:数组严格递减,只能留1个元素,需删除长度为4的子数组。示例3:0解释:本身已非递减,无需删除。
2025-10-29 10:51:18
638
原创 完美对的数目
在这道题中,我们需要找到数组中满足特定条件的“完美对”数目。通过分析条件的数学本质,结合双指针技巧,可以将时间复杂度优化到。这种解法通过“排序+双指针”的组合,高效地将原本暴力枚举的。,在时间效率上有显著提升,适用于大规模数据场景。即其中一个数的绝对值是另一个数绝对值的。通过代数分析(不妨设。
2025-10-27 16:38:38
423
原创 满足条件的子序列数目
通过这种“双指针+快速幂”的组合,我们高效地解决了这道子序列计数问题,既保证了逻辑的简洁性,又确保了时间效率。题目要求我们统计数组中。的数目,使得子序列的。
2025-10-27 11:38:57
246
原创 找到K个最接近的元素
逆向思维,首先知道的是原数组已经排好序了,如果正向去找的话,就得从最接近x的元素开始找,首先使用二分查找去找数组中最接近x的元素,然后用背向双指针去一个一个找,然后对结果数组进行排序,这是比较直接的一个想法。但是使用逆向思维的话,首先可以发现,按正向的方式去寻找的话,答案一定是原数组中连续的一部分,那么就可以从两端去寻找n-k个不接近x的元素,剩下的就是答案。总之这种逆向思维的题还是很巧妙的,能够大大简化原做法。
2025-10-19 15:37:33
212
原创 执行操作后的最大MEX
同余原理,可以发现,模value相等的数是等价的,可以相互转换,所以用一个数组记录下模value等于每个值的个数,然后从0开始枚举非负整数,模value相等就说明可以转换过来,直到出现一个无法转换的数字,就是答案。
2025-10-16 11:01:24
289
原创 最长优雅子数组
对于一个子数组 A[i..j],要满足任意 x,y∈A[i..j] 且 x=y 时 x & y=0,这是一个非常严格的条件。由于 1≤nums[i]≤109,数字最多有 30 位(230≈109),因此我们需要一个大小为 30 的数组。),如果 x 的第 b 位是 1,则 y 的第 b 位必须是 0;已经 ≥1,这意味着窗口中已经有另一个元素在第 b 位上是 1,因此添加。例如,如果子数组中有元素 x 的第 5 位是 1,那么子数组中的。会导致 x & nums[r]=0,破坏了优雅子数组的条件。
2025-10-15 11:04:59
338
原创 和相同的二维子数组
答案就是元素和 ≥k 的子数组个数,减去元素和 ≥k+1 的子数组个数。这里把 > 转换成 ≥,从而可以把滑窗逻辑封装成一个函数 solve,然后用 solve(k)−solve(k+1) 计算,无需编写两份滑窗代码。注:也可以把两个滑动窗口合并起来,维护同一个右端点 right 和两个左端点 left1和 left2。注:也可以把问题变成 ≤k 减去 ≤k−1,即两个「至多」。总结:「恰好」可以拆分成两个「至少」,也就是两个「越长越合法」的滑窗问题。,我把这种写法叫做三指针滑动窗口。
2025-10-12 10:20:54
186
原创 字符至少出现K次的子字符串
用一个变量来记录当前窗口数量大于等于k的字符的个数,维护这个变量就好了。这一招是真好用,在判别窗口是否符合要求的时候。
2025-10-10 19:04:26
269
原创 最小覆盖子串
这题思路不难,重点在于优化,如果采用常规做法的话,在判断窗口是否符合条件的时候,就是每次遍历长度为58的win数组来判断,这样做的话复杂度是O(58*m+n),但是实际上这样做是没有必要的,下面就是很重要的优化方法,这个方法适用于很多类似的判断窗口是否符合条件的情况。维护一个变量less,代表窗口中子串字符的数量小于目标子串字符的个数,当less等于0的时候就说明满足条件。在滑动窗口的过程中维护less变量即可。
2025-10-10 10:55:08
263
原创 无限数组的最短子数组
独立做出来1900分的题了,首先看数组之和是否小于target,如果小于,则target必然包含整数倍个nums的所有元素,然后把原nums数组复制一遍,考虑头和尾就好了。
2025-10-09 15:06:09
137
原创 使数组连续的最小操作数
难题,这题看完题解然后自己写完,感受就是正难则反,根本不关心哪个元素会变成哪一个,对原数组进行排序去重之后,枚举修改之后数组的最大值,找到最长的不用修改的子数组的长度,最后用总长度减去这个,就得到最少的操作数。
2025-10-07 20:07:44
152
原创 两个无重叠子数组的最大和
基本上一模一样,利用dp的思想先维护一个数组dp,dp[i]表示索引[0...i]范围内符合要求的子数组最大值,然后第二次遍历,维护当前窗口值,再加上这个窗口之前的dp[l-1],选出最大值即可。需要注意的是这题需要这样做两边,左边first个右边second个,左边second和右边first个,选出其中的最大值即为答案。
2025-10-06 18:46:27
210
原创 两个线段获得的最多奖品
由于 dp_left[l−1] 已经记录了在 [0,l−1] 索引范围内能获得的最大奖品数,这个值已经考虑了所有情况。我们首先要高效地计算出:对于数组中的每个位置 i,如果以 prizePositions[i] 为右端点(或右侧),能形成的长度为 k 的线段所能获得的。窗口 [l,r] 始终保持 prizePositions[r]−prizePositions[l]≤k。对于每一个右端点 r,它对应的第二个线段是 [l,r],获得的奖品数是。能获得的最优奖品数,这个线段的右端点在 i 或 i 的左侧。
2025-10-06 17:37:47
568
原创 最高频元素的频数
窗口维护的变量就是当前窗口全部改成最大值所需要的操作数,每当一个元素进入窗口,需要加的就是(nums[r]-nums[r-1])*(r-l),然后移动左窗口来保证这个变量不大于k,记录窗口长度最大值,就是答案。关键点在于如何建立一个可以滑动更新的变量,分析题目之后发现答案是与元素下标无关的,那就对数组进行排序,排序之后思路会清晰很多。
2025-10-04 13:46:22
148
原创 分割等和子集-背包dp
遇到这种问题的时候,先用背包dp的思路去分析,然后根据具体问题具体的去定义状态。非常直观的就可以想到背包dp,从一个序列中选出和为target的子序列,与。
2025-10-03 12:59:40
180
原创 单词拆分-dp
这题算是比较经典的题了,我一开始把这个问题想成了二维dp,但是实际上这样是错误的,因为字典是无限制的,原字符串是有顺序的,而不像背包问题,背包问题的容量限制只是一个数字。这里展示了错误做法和正确做法。
2025-10-03 12:54:47
312
原创 使库存平衡的最小丢弃次数
这题的思路倒是挺直接的,定长滑动窗口就可以,但是做的时候犯了一个错误,如果一个元素在进窗口的时候就被丢弃了,那么当这个下标出窗口的时候,不应该再把它的频率减一。因为出窗口是将这个下标的元素的频率减1,但是前提是这个元素在窗口中,如果一开始就被丢弃了,那再把它的频率减一,就会导致错误。正确的做法是,如果一个元素在进入窗口的时候被丢弃了,那么就把这个位置的元素置为0,这样就不会影响后面出窗口的效果了。
2025-10-02 16:54:20
199
原创 找出最长等值子数组
第二种做法相对来说更好理解,首先把相同数字的下标放在一组,然后去遍历每一个组,在每个组内,就是标准的滑动窗口了,pos[r]-pos[l]+1表示在原数组中的区间长度,r-l+1表示窗口内当前数字的个数,两者相减就得到了数组内的“异常元素”的个数,维护窗口内“异常元素”的个数不超过k个,取遍历过程中的最优解。首先概括一下题目,从原来的题目说起,以前的题目就是说某个区间内只允许出现k个不一样的元素,求区间的最大长度,比如。让我比较吃惊的是这种方法的复杂度居然是很良好的,与我的感觉不太一样。
2025-10-01 19:26:11
305
原创 每种字符至少取K个
从两端取至少k个,相当于从中间的连续部分取至多cnt_a-k,cnt_b-k,cnt_c-k个,这又回到了满足约束的连续子数组问题,用变长滑动窗口解决,记录最长窗口长度,最后用字符串总长度减去最大窗口长度就可以得到答案。从两端取到每个字符各至少k个,先计算出原字符串中a,b,c的个数,如果有小于k的,直接返回-1.从两端取数字,根据之前的经验,直接用逆向思维,考虑中间的连续部分。
2025-09-30 19:20:30
309
原创 数组的最大美丽值
第二种做法也是比较有启发价值的,由于要求的是子序列的长度,跟数组的顺序无关,所以可以对数组进行排序,排完序之后就很直观清晰了,求一个区间,这个区间满足最大值和最小值之差小于等于2*k,求这个区间的最大长度,也是很典型的变长滑动窗口问题。的启发,这题可以映射到值域,然后求窗口大小为2*k+1的最大窗口累加和。这种做法的时间复杂度是O(n),但是空间复杂度较高,取决于数组的最大值。这题有两种做法,一个是定长的滑动窗口一个是变长的滑动窗口。很相似,都是排序之后的变长滑动窗口。首先看我自己的想法,受。
2025-09-30 16:27:02
277
原创 将x减到0的最小操作数
对于这道题,目标是求两端之和等于x的最小元素个数,也就是求连续和等于x的最大元素个数,直接用滑动窗口解决。很相似,都是从两端拿数,转换为中间的连续子数组,从而用滑动窗口求解。
2025-09-29 22:47:09
247
原创 水果成篮-越短越合法
如果 fruits[right] 加入哈希表后,发现哈希表的大小超过了 2,那么子数组不满足要求。移动子数组的左端点 left,把 fruits[left] 的出现次数减一,直到哈希表中的元素种数等于 2。子数组越长,包含的元素越多,越可能不满足题目要求;反之,子数组越短,包含的元素越少,越可能满足题目要求。⚠注意:如果 fruits[left] 的出现次数变成 0,减少cnt,表示子数组内少了一种元素。同时用一个哈希表维护子数组内每个元素的出现次数,用一个变量cnt维护哈希表的大小。
2025-09-29 15:36:13
294
原创 滑动窗口为什么有效?
很多题使用滑动窗口可以有效的用O(n)的复杂度解决,或者将O(n^3)的复杂度优化到O(n^2)甚至O(n),但是我始终不明白这个方法到底为什么能优化,为什么它的优化是有效的?Gemini的答案:
2025-09-29 15:19:05
125
原创 尽可能使字符串相等
注意到两个子字符串的开销就是他们的每个字符之差的绝对值求和,是典型的区间和问题,所以可以使用前缀和来快速计算两个子串的开销,然后用滑动窗口去寻找满足条件的最长子串即可。一开始理解错了题意,以为子字符串的位置是任意的,但是题目中说的是s和t的对应位置的下标之差,所以根本没必要排序或者二分查找了。最难的部分还是理解题意+前缀和。
2025-09-29 15:07:11
243
原创 使数组平衡的最少移除数目
首先这题的答案与数字的顺序是没有关系的,所以可以先对数组进行排序,排完序之后,需要求的就是一个区间,满足max<=k*min,求这个区间的最大长度,用数组总长度减去最大长度就得到答案。
2025-09-29 14:31:03
227
原创 交换元素后的最大交替和
因为交换是无限次数的,所以可以相互交换的所有元素相当于一个连通分量,在这个连通分量内贪心策略,排序之后把大的放在偶数位,小的放在奇数位,这样就可以使得交替和最大了。连通分量用并查集维护,注意在寻找一个点的祖先的时候要使用find_root函数来寻找,不能简单地使用f[i]。比赛的时候做的时候没有考虑连通分量,直接把所有可交换的都当成一个了。
2025-09-28 17:30:52
240
原创 删除子字符串后不同的终点
分析之后可以发现,终点的位置和路径的顺序没有关系,只和路径当中U,D,L,R的个数有关,于是就可以用定长滑动窗口来解决了。需要注意的就算映射到哈希表的地方,把两个数压缩为一个long long类型的数,然后放到哈希表。
2025-09-28 16:21:33
322
原创 分割数组得到最小绝对差
有了上一次遍历得到的结果之后,再遍历一次,枚举分割位置,这样就可以很轻松的判断是否满足递增和递减的条件,并且根据前缀和可以很容易的求和。一次遍历,记录以每个元素结尾的最长递增子数组的长度以及最长递减子数组的长度,同时记录前缀和数组。
2025-09-28 16:16:46
180
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅