- 博客(22)
- 收藏
- 关注
原创 LeetCode 热题 239.滑动窗口最大值
初始时队列是空,每次进来一个新数字,先判断队头下标距离 i 是否超过了 k,超过了则要出队,同时我们不断比较一下队尾和新进来的数字的大小,如果队尾的数字比新来的数字小,那队尾数字就“永无出头之日”,直接出队,直到碰到比新来的数字大的停止。,我们可以优化一下,窗口向右移动,每次窗口前面进去一个新数字,窗口末尾出去一个数字,我们可以用双向队列来模拟,每次把尾部数字弹出,再把新数字压入队头。这里有个点就是,假如新进来的是一个比较大的数字,比如 5 ,那队列中比这个数更小的数字就不可能成为最大值了,就像。
2025-09-19 11:47:08
175
原创 LeetCode 热题560.和为k的子数组 (前缀和)
某段数组的和,很容易想到用前缀和求解,i 到 j的子数组的和为 k 我们可以转化成 s[j] - s[i - 1] == k,所以 s[i - 1] =s[j] - k。所以要求以 j 结尾的和为 k 的子数组的个数 相当于求 有多少个前缀和为 s[j] - k的前缀和 s[i] 就行。这里我们用哈希表来存前缀和出现的次数。
2025-09-15 23:36:52
210
原创 LeetCode热题 438.找到字符中所有字母异位词 (滑动窗口)
这跟 无重复字符的最长子串 所用的算法是一样的,也是维护一个窗口(长度和 p 一样),然后比较这个窗口中的字母出现频率和 p 中字母出现的频率是否一致。然后继续判断,一致就把当前窗口的起始点加进答案。这里可能有疑问,就是怎么判断字母出现的频率是否一致,我们可以用两个vector,比如加进来一个 c,那我们就把 cnt[‘c’ - ‘a’] ++ ,然后比较就直接比较两个数组是否想等,因为 vector 重载了 operator==,所以可以直接比较两个数组是不是相同。
2025-09-12 21:15:06
224
原创 LeetCode 热题 160.相交链表(双指针)
前面的 a + c + b = b + c + a,那么不管 a 和 b 等不等,如果AB相交 i 和 j 总能在某一时刻同时指向相交的点,并且如果没有相交的点,他们也同时指向空。我们可以用双指针,i 指向a的头,j 指向b的头,然后一个个比较然后不同就往下走,但是这里有个问题,就是可能不同步,i 和 j 经过相交节点的时间可能不同。链 A 分为两段:不相交的 a 部分 + 相交的 c 部分。i 走的路程是 a + c + b + c。j 走的路程是 b + c + a + c。
2025-09-12 00:03:59
191
原创 LeetCode 热题 3.无重复字符的最长子串
我们可以维护一个区间,让右指针一直往右走,直到区间里有字母的个数 > 1那就让左指针开始往前走,直到区间里字母的个数都 < 1.求最长无重复字符的子串其实就是 求最长区间 [i, j] ,使得区间里没有任何字符的个数 > 1。这个写法因为 i 只增不减,j 只增不减,两个指针各走一边 所以是 O(n)的。枚举所有子串,检查每个子串是否有重复字符。
2025-09-11 00:04:05
165
原创 LeetCode 热题 42.接雨水(双指针写法)
我们可以在这里优化一下,用两个指针 l ,r 从 0 和 n-1 出发,动态记录目前左右两边最高的柱子高度,边走边更新。每一步比较一下当前左右两边最高柱子的高度谁矮,矮的一边往里面走一格,并立即计算这根柱子和这根柱子所在侧的最高柱子的高度差,这就是这根柱子的接水量,因为我们是先更新最高柱子的高度,再计算接水量,所以这根柱子的高度一定 <= min(左边最高柱子的高度, 右边最高柱子的高度),并且 水面高度已经被矮墙卡死,不会多算。最简单想到的就是遍历一遍,先存下没个柱子左右两边最高的柱子高度。
2025-09-10 20:59:42
370
原创 LeetCode热题 42.接雨水
我们确保这个栈是递减的,遍历每个柱子i,如果这个柱子比栈顶矮,那就让这个柱子进栈,这里对于i来说已经有了左边的墙,右边的墙还没来,我们继续遍历。当遍历到柱子 i 高度大于栈顶柱子的高度,那柱子 i 就是右墙了,此时栈顶柱子就是那个接水坑的坑底。我们先把坑底弹出栈,然后计算 宽 w = 此时柱子 i 的下标 - 栈顶柱子的下标 - 1。当前柱子接水量 = min(左边最高柱子的高度, 右边最高柱子的高度) − 当前柱子高度。再计算 高 d = min(栈顶高度,柱子 i 的高度) - 坑底的高度。
2025-09-09 23:39:09
421
原创 LeetCode热题 15.三数之和(双指针)
这时候我们可以想到 对于 a + b + c = 0求不重复的三元组,等价于 固定一个 a,求 b + c = -a 的不重复的 二元组。最简单的最暴力的想法就是三重循环便利所有可能的三元组,检查他们的和是否为零,并去除重复的组合。这种的时间复杂度是0(n^3)。
2025-09-08 22:54:55
221
原创 练习题(动态规划)
假设,我们想求一下当前这个数 ai,以ai结尾的最长子序列,那我们要从序列里找到一个最大的小于ai的序列,假设长度为4的上升子序列的最小结尾值是q4,q4是最大的小于等于ai的数,那把ai接过去,那这样我们就得到了一个以ai结尾的长度为5的上升子序列,假设长度为5的上升子序列的最小结尾是q5,由于q4是最大的小于等于ai的,那么q5就是大于等于ai的,所以ai一定不可能接到长度是5的子序列后面,因此,以ai结尾的上升子序列的最大长度就是5,那如何找到最大的小于等于ai的数呢?一,最长上升子序列2。
2024-10-22 21:54:33
929
1
原创 动态规划2
注意方程的变换,应该找数字下面的两个数字坐标,再加上本身a[i][j]如果还是嫌麻烦,我们可以倒序dp,这样边界问题一点都不用考虑了。如果想要知道最长子序列是什么的话,可以记录当前点是从哪个点来的。当然,初始也不用思考边界问题,直接把所有都初始化。这里输出的序列是倒着输出的,正着输出的话可以用栈。代码很简单,直接用状态转移公式。是指递推方程有明显的线性关系。
2024-10-21 20:57:22
234
原创 动态规划1
正序的情况下,假设循环到第二轮,i = 2,j循环到4了,那么f[4] = max(f[4], f[4 - 2] + w[2]),这里用到了f[2]对应二维应该是f[1][2],但是一维下却成了f[2][2]也就是f[i][j - v[i]] 很显然跟公式不对,因为f[2]在之前j循环到2的时候被更新了一轮,从第i - 1 轮更新到第i轮了,也就是被污染了。但是逆序的话当我们j枚举到4的时候,这里用的 f[2]是还没有被更新的第i - 1轮的 f[2] 正好对应二维的 f[i - 1][j - v[i]]
2024-10-16 23:05:37
640
原创 数学知识3
所有输入系数以及常数均保留两位小数,绝对值均不超过 100100。因为 a > b, b含有的素数a都包括。要根据数据范围选择不同的方法。为何代码里筛素数只筛了a?
2024-10-09 22:58:06
236
原创 数学知识2
第一种情况时,pj是i的最小质因子,pj小于i的所有质因子,所以pj同时也是i * pj的最小质因子,就有了上面的式子,而 i * (1 - 1/pj) ... (1 - 1/pk)正好是i的欧拉函数,所以简化成phi[i] * pj。第二种情况时,pj 不是i的质因子,又因为 pj * i 的质因子有 pj 和 i 的所有质因子,所以就是第二个式子,而同理把 i * (1 - 1/p1) ... (1 - 1/pk) 简化成phi[i]p是质数,p是质数,p是质数,不是质数就不行了,费马定理就不能用了。
2024-09-26 21:49:09
366
原创 搜索与图论3
定义:在一个加权图(即边具有权重或成本的图)中找到一棵包含所有顶点的树,使得这棵树中的所有边的权重之和尽可能小。题目对应一般是无向图,正负边都没关系。
2024-09-07 16:38:44
1090
原创 搜索与图论2
假如这种情况,要求1到5的最短路,发现1根本走不到5,但是4经过松弛操作后会更新5号点,显然0x3f3f3f3f < 0x3f3f3f3f - 999,,所以5号点会更新成0x3f3f3f3f - 999,所以这时候判断dist[n] == 0x3f3f3f3f显然不合适,边长的绝对值不超过100000,减的也不会太大,和0x3f3f3f3f在一个数量级即可。
2024-08-18 16:02:40
942
原创 八数码问题
题目类似于数字华容道,可以抽象一下,把每一个状态当成一个节点a,它的变化后的下一个状态是另一个节点假如是b,我们就连一条a到b的边,权重是1,例如,状态表示:我们可以把二维三乘三的矩阵变成一维的string来存储,用一个字符串来表示一个状态,队列定义的话直接queue<string>q;状态转移,我们先把字符串想象成三乘三的样子,把x的上下左右分别枚举,把这些位置的数移动到x上,最后再把它变成string。在一个 3×3的网格中,1∼8这 8个数字和一个 x 恰好不重不漏地分布在这 3×3的网格中。
2024-05-21 17:43:53
282
1
原创 哈希表算法
作用:把一个复杂的数据结构映射到比较小的区间0到n,比如把0到10^9的数映射到0到10^5内离散化可以看做是一个极其特殊的哈希方式这就会产生冲突,就是某些数映射成同一个数,为了处理冲突有两种方法,拉链法和开放寻址法哈希算法是一个期望算法,在算法题里面一般只会添加一个数和查找一个数,一般不会有删除操作,如果有删除操作,一般不会真的删除某个点,可以开一个bool数组在删除的点上做个标记。
2024-04-23 22:33:50
1750
原创 堆排序(如何手写堆)
同上面,不过不需要考虑是要往上移(k位置上的数变小了)还是往下移(k位置上的数变大了),down和up只会做一个。####3.删除最小值 heap[1] = heap[size];####4.删除任意一个元素 heap[k] = heap[size];是一个完全二叉树,除了最后一层节点之外,上面都是非空的,最后一层从做到右以此排布。用一维数组存储,下标从1开始,1为根节点,x的左儿子为2x,x的右儿子为2x+1。down(x) 把一个节点往下移 up(x)把一个节点往上移。
2024-04-16 22:26:12
620
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅