- 博客(37)
- 收藏
- 关注
原创 代码随想录算法训练营-Day42
因为如果你不强制它以 nums[i] 结尾,你就根本无法判断下一个数字 nums[i+1] 能不能拼接在它后面!我们定义二维数组:int[][] dp = new int[nums1.length + 1][nums2.length + 1];即 nums[i] <= nums[j]。一旦接上去,新的子序列长度就变成了以 nums[j] 结尾的长度加上 nums[i] 自身(即。情况 B:不满足递增(nums[i] <= nums[i-1])情况 A:满足递增(nums[i] > nums[i-1])
2026-03-03 16:52:21
653
原创 代码随想录算法训练营-Day40
在代码实现中,你既可以在买入的时候提前扣掉手续费,也可以在卖出的时候结算扣除。跟无限次交易完全一样,我们定义二维数组:int[][] dp = new int[n][2];我们定义二维数组:int[][] dp = new int[n][2 * k + 1];定义二维数组:int[][] dp = new int[n][3];为了完美契合冷冻期的规则,我们必须定义 3 个完全互斥的状态。dp[i][0] 的绝对物理含义:在第 i 天结束时,手里。dp[i][1] 的绝对物理含义:在第 i 天结束时,手里。
2026-03-02 11:58:06
562
原创 代码随想录算法训练营-Day39
dp[0][4] = 0:第一天买入,卖出,再买入,再卖出。我们定义一个二维数组:int[][] dp = new int[n][2];我们定义一个二维数组:int[][] dp = new int[n][2];我们定义二维数组:int[][] dp = new int[n][5];dp[0][2] = 0:第一天买入,然后同一天立刻卖出。(注意:这里的“最大现金”允许是负数,因为买入股票要花钱。dp[0][1] = -prices[0]:第一天强行买入。dp[0][0] = 0:不操作,没钱。
2026-03-01 22:50:06
611
1
原创 代码随想录算法训练营-Day38
收益:既然当前这间没偷,那么第 i-1 间房是安全的(可以偷,也可以不偷,反正它已经是前 i-1 间房的最优解了)。收益:既然第 i-1 间不能碰,那么小偷前序的合法最大收益就是考虑前 i-2 间房的最大收益(即 dp[i-2])。公式:dp[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);收益:当前节点里的钱 node.val + 左孩子不偷的收益 left[0] + 右孩子不偷的收益 right[0]。代价:父子不能同偷。
2026-03-01 14:25:17
655
原创 代码随想录算法训练营-Day36
01 背包(物品限 1 次):外物内包(外层for循环遍历物品,内层for循环遍历背包容量),内层倒序。完全背包(物品无限次):外物内包(外层for循环遍历物品,内层for循环遍历背包容量),内层正序。完全背包变种:外包内物(外层for循环遍历背包容量,内层for循环遍历物品),内层正序。依旧是排列数问题,此时依旧外层遍历背包容量,内层遍历物品(要爬的台阶数量)这是一个排列数问题。
2026-02-28 14:56:24
77
原创 代码随想录算法训练营-Day32
公式:想要到达 i,要么从 i-1 走一步(花费 dp[i-1] + cost[i-1]),要么从 i-2 走两步(花费 dp[i-2] + cost[i-2])。定义:dp[i] 表示到达第 i 级台阶(还未支付第 i 级的费用,或者说是站到了第 i 级上)的总花费。dp[0] = 0:因为题目说你可以选择从下标 0 或 1 开始,所以站到 0 号台阶不需要钱。结果:dp[n](题目要求的楼顶是数组长度 n,即越过最后一个元素的位置)。dp[1] = 0:同理,直接跳到 1 号台阶也不需要之前的费用。
2026-02-17 11:40:03
54
原创 代码随想录算法训练营-Day27
如果 preDiff 和 currDiff 符号相反(一正一负),说明出现了拐点(摆动),结果加一。初始化:maxSum 设为最小值(或第一个元素),curSum(当前连续和)设为 0。原因:贪心需要每次拿“最大/最小/最优”的元素,有序数组是做贪心的基础。更新状态:既然选了最好的,就不用回溯(不后悔),直接更新结果。局部最优:大饼干喂给胃口大的(或者小饼干喂给胃口小的)。currDiff:当前一对元素的差值(当前的坡度)。preDiff:前一对元素的差值(上一段的坡度)。全局最优:喂饱尽可能多的孩子。
2026-02-10 20:56:45
360
原创 代码随想录代码训练营-Day25
如果前一个没用过 (false):说明我们处于同一层(Horizontal)。前一个已经在这个位置试过了,我是重复的,要剪枝。如果前一个正在用 (true):说明我们处于同一树枝(Vertical)。前一个是我的父节点,我是它的子节点,可以共存。的意思是:“前面的兄弟(值相同的元素)刚才已经处理完、并且已经回溯了(状态重置为 false),现在轮到我了。由于数组无法进行排序,则通过Set来进行去重。需要一个 used 数组。最重要的是树层去重的理解。
2026-02-10 20:15:13
42
原创 代码随想录算法训练营-Day24
优化回溯写法:对于 StringBuilder,最安全的回溯方式不是计算删几次,而是记住进入递归前的长度,回来时直接 setLength 恢复。调整终止条件:当“点的数量”为 3 时,不要立刻返回,而是检查剩下的字符串是否合法。子集问题:我们要遍历整棵树,树上的每一个节点(除了根节点外的每一次递归状态)都是一个合法的子集。结论:在子集问题中,不需要等待特定的终止条件,而是每进入一层递归,就立刻收集一次结果。组合问题 / 分割问题:我们像是在树上找特定的果实,通常只有走到树的。
2026-02-06 21:53:24
54
原创 代码随想录算法训练营-Day23
在组合问题中,通过 startIndex 和循环变量 i 来决定选取哪个数字。在分割问题中,通过 startIndex 和循环变量 i 来决定在哪里切一刀(即截取哪一段子串)。虽然通过在调用dfs时令 startIdx=i+1 避免了重复使用同一个位置的元素,但没有避免在“同一层”使用数值相同的不同元素。分割问题(Partitioning)本质上就是组合问题的一种变形。即,需要在for循环(横向)中进行去重。这题与上一题最大的区别在于,上一题是。来进行递归条件、剪枝的判断。
2026-02-05 20:10:00
46
原创 代码随想录算法训练营-Day22
需要注意,这道题遍历的是String,而不是数字数组。然后依旧遵循 回溯的三部曲:做选择 -> 递归 -> 撤销选择。修改dfs方法中的参数的语义。用来避免解法一中的反复求和的开销。回溯的三部曲:做选择 -> 递归 -> 撤销选择。时间复杂度:叶子个数(
2026-02-04 21:59:05
330
原创 代码随想录算法训练营-Day21
对于当前访问的结点,如果结点为空结点,直接返回空结点;如果结点的值小于 low,那么说明该结点及它的左子树都不符合要求,我们返回对它的右结点进行修剪后的结果;如果结点的值大于 high,那么说明该结点及它的右子树都不符合要求,我们返回对它的左子树进行修剪后的结果;如果结点的值位于区间 [low,high],我们将结点的左结点设为对它的左子树修剪后的结果,右结点设为对它的右子树进行修剪后的结果。再第二次遍历进行修改,将当前节点的值修改为累加和,然后再减去当前节点的原值。思路2:反向中序遍历。
2026-02-03 15:12:38
48
原创 代码随想录算法训练营-Day17
第一次因为代码本身只有一个参数int[],就在方法里构造新的子数组进行传递了,但是反复构造数组在开销上变大,可以再写一个方法进行递归,方法只传原数组,但是增加左右指针限定区间范围。先找到数组的最大值及其索引,然后构造该节点,然后递归构造该节点的左孩子、右孩子,然后问题就回归到如何把左孩子、右孩子对应的数组传递出去。灵神的前序遍历思路。而外定义一个dfs函数,定义两个参数,分别表示从根到当前节点路径上的最小值和最大值。
2026-02-02 14:29:53
50
原创 代码随想录算法训练营-Day16
利用这个 leftSize,把 postorder 数组也切成两半(左子树部分和右子树部分)。后序遍历 (Postorder) 的结构是:[ 左子树 | 右子树 | 根节点 ]中序遍历 (Inorder) 的结构是:[ 左子树 | 根节点 | 右子树 ]这个位置左边的元素个数,就是左子树的大小 (leftSize)。传递父节点的当前和信息,属于自顶向下传递。从 postorder 的末尾拿到根节点的值。在 inorder 中找到这个根节点的位置。标准的层序遍历模板题目。
2026-01-29 23:15:46
35
原创 代码随想录算法训练营-Day15
自底向上:返回值法只依赖子树状态经典场景:最大深度、是否平衡二叉树、二叉树直径、最近公共祖先自顶向下:回溯必须依赖父节点信息所有路径、路径总和、根节点到叶节点数字之和。
2026-01-28 23:32:19
406
原创 代码随想录算法训练营-Day13
递归是利用系统帮我们维护的栈,迭代则自己new Stack。需要额外记忆的题目:二叉树的最大深度、二叉树的最小深度。二叉树的迭代遍历,参考上述的BFS的空指针标记法模板。实现方式:递归法、迭代法(着重记忆空指针标记法)针对DFS,无论是使用递归还是迭代,本质上是利用。二叉树的递归遍历,参考上述的DFS的前中后序模板。DFS 的三种遍历规则:前序、中序、后续遍历。二叉树的层序遍历,参考上述的层序遍历模板。主要从二叉树的遍历方式区分。,所以是new Queue。
2026-01-26 22:50:43
410
原创 代码随想录算法训练营-Day11
针对ab-c/这一表达式,计算方法为:a入栈,b入栈,遇到运算符号,取出栈顶两个元素,注意顺序,取出的第一个是b,第二个是a,然后执行计算d=a-b,再将d压入栈,同理将c压入栈,遇到除号…使用一个双端队列维护数组nums的序号,保证队首的序号对应的值始终是当前窗口下nums中的最大值,且保证值单调递减,队首始终维护最大值的序号。右边入队(判断队列是否为空,若不为空,则进行单调性维护)→左边出队→维护答案。至于如何将中缀表达式(即人类最常见的表达式)改为逆波兰表达式,可以参考。使用小顶堆进行处理。
2026-01-26 13:18:12
292
原创 代码随想录算法训练营-Day10
通过使用栈来实时将相邻重复的字符进行弹出,注意最后java的方法q.pollLast()。因为将Deque作为栈使用的时候,push方法是将元素压入栈首,也是队列的队首,那么要获取先进入的字符(栈底,或者说队列的队尾),需要使用队列的pollLast()方法。使用一个队列即可,每次将元素送入队列之前,先记录队列长度n,然后将元素送入队列,接着遍历队列依次将前n个队列元素弹出然后再加入队尾。将一个栈当作输入栈,用于压入 push 传入的数据;另一个栈当作输出栈,用于 pop 和 peek 操作。
2026-01-24 14:37:06
202
原创 代码随想录算法训练营-Day09
思路2:配合StringBuilder。去除多余空格 → 反转整个字符串 → 逐个反转词。思路:如果s可以由重复的子串构成,则s必定是 (s+s)[1:-1] 这个字符串的子串。思路:将整个字符串看作一个环,右转就是整个字符串位移k位,尾部元素逐个添加到头部。思路1:调用Java的字符串api。
2026-01-22 22:16:58
233
原创 代码随想录算法训练营-Day08
如果从前往后替换,写入 “number” 占用的 6 个位置会覆盖掉后面还没处理的字符。从后往前填坑,可以保证 i 始终走在 j 后面(或者重合),写入的位置永远是“安全的”。整个过程分为三个主要步骤:统计扩容 → 数据迁移 → 倒序替换。注意最后一个区间的右开端点要和n取最小值,防止区间越界。其中,双指针倒序替换是核心,为什么。双指针在原数组中进行交换。
2026-01-21 14:09:38
352
原创 代码随想录算法训练营-Day07
但是去重思路需要注意,不能再判断单个数和target的关系了,因为target可能是负数,如果在nums[i] > target的情况下直接break,可能会遗漏正确答案,即nums[i+1]此时也是负数,则可以出现nums[i] > target 但是 nums[i] + nums[i+1]<target 的情况。经典题目,排序后,使用双指针+去重+优化。每个数字都一定要去重!思路与三数之和一模一样。排序后,多循环一重,双指针+优化+去重。的解题思路一致,使用哈希表记录每个二者之间每个字符的差值即可。
2026-01-20 13:37:46
202
原创 代码随想录算法训练营-Day06
通过集合1来存储第一个数组的数,然后通过遍历第二个数组,判断其数字是否位于集合1中,若存在则放置与集合2中,将集合2转换为数组输出。根据无限循环来判断是否为快乐数,将快乐数的每次计算结果保存在哈希集合中,如果重复出现集合中的结果,则进入循环,说明不是快乐数。思路2:忘记在哪看到的思路,两个字符串如果互为字母异位词,则它们的字符数组排序后完全相等,可以拓展至unicode字符。思路1:通过数组作为哈希表来存储各个字母的出现次数。如果二者的各个字符的出现次数一致,则为字母异位词。
2026-01-18 22:56:25
209
原创 代码随想录算法训练营-Day04
相遇时,记慢指针走了x+y步(x:进入环之前的路程、y:慢指针在环内走的路程,此长度未满环一圈),快指针走了x+2y+z步(z:环的长度减去y的长度,即默认y+z等于环的长度。由快指针速度为慢指针的2倍得知:x+2y+z == 2(x+y),所以x==z,即慢指针该圈剩余的路程==进入环之前的路程,则再设置一个指针从头节点出发,慢指针从相遇点出发,二者速度相同,则一定在环节点处相遇。快指针先走n步,然后慢指针与快指针同时走,快指针到null的前一位时,慢指针位置即为需要删除的位置前一位。
2026-01-17 14:11:54
229
原创 代码随想录算法训练营-Day03
需要维护好自定义链表的size(长度)属性,并根据虚拟头节点head来进行查询,其他方法使用头节点时必须赋值使用,不能直接操作head。两个相邻的指针从头(头节点前面为null)依次进行反转处理即可,知道右侧的指针指向null说明处理结束。虚拟头节点方法进行统一处理即可。
2026-01-16 21:37:05
98
原创 代码随想录算法训练营-Day02
没空写了,明天再更新。具体思路:用前缀和将3次暴力循环的第一次优化掉。前缀和,可以解决数组任何子区间和的方法。的模拟思路,最好背,没为什么。
2026-01-16 00:00:36
192
原创 代码随想录算法训练营-Day01
快慢指针,快指针遍历整个数组的元素,慢指针相当于将数组原地视为一个空的数组,以慢指针为索引一个个填充满足条件的、快指针所指向的数字。利用数组有序、平方后数值大小(本质对比数组的首尾数字的绝对值大小)的特点,将绝对值较大的数字从末尾开始插入新的数组中。
2026-01-14 20:05:31
436
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅