- 博客(53)
- 收藏
- 关注
原创 代码随想录算法训练营第六十天 | 84.柱状图中最大的矩形
84.柱状图中最大的矩形本题与接雨水相近。按列来看,是要找到每一个柱子左右第一个比它矮的柱子,即对于该柱子来说所能组成的最大面积,将每个柱子所能得到的最大面积进行对比最终得到最大矩形。双指针法。
2023-12-11 11:19:22 530
原创 代码随想录算法训练营第五十九天 | 503.下一个更大元素II,42. 接雨水
503.下一个更大元素II代码随想录上实现两次循环的方法我觉得也挺有参考价值的,是将循环终止结果 * 2,每次索引时 % nums.size()。42. 接雨水。
2023-12-08 16:46:54 541
原创 代码随想录算法训练营第五十八天 | 793.每日温度,496.下一个更大元素 I
最开始的思路是想只针对 nums1 中的各个数来求其下一个更大的元素,可能会存在很多重复计算;如果还是使用单调栈来实现这一题,那么其实是针对 nums2 中的每一个元素都求出其下一个更大的元素,再针对 nums1 中这些数的位置进行结果输出。求某数右边最近的大于自己的数,采用单调栈的方法。日期早的数先进栈,每次遍历到某一天就将该天温度依次与栈中各天温度进行比较,若大于栈中温度,则该天即为栈中天的最近大于自己温度的那天。
2023-12-07 16:03:41 467
原创 代码随想录算法训练营第五十七天 | 647. 回文子串,516.最长回文子序列,动态规划总结篇
(3)寻找 dp 的前一状态时,i 不断 +1,j 不断 -1,i 最大不超过 j,j 最小不超过 i,所以需要初始化 i == j 的情况,dp[ i ][ i ] = 1;若 j - i <= 1 dp[ i ][ j ] = true;(1)dp[ i ][ j ] 表示以 i 为开头、j 为结尾的字符串的最长回文子序列;(1)dp[ i ][ j ] 表示从 i 到 j 的字符串是否为回文子串;(2)若 s[ i ] == s[ j ](4)i 从大到小,j 从 i 到大。
2023-12-06 16:22:59 543
原创 代码随想录算法训练营第五十六天 | 583. 两个字符串的删除操作,72. 编辑距离
但是,实际上 dp[ i - 1 ][ j - 1 ] + 2 == min( dp[ i - 1 ][ j ] + 1, dp[ i ][ j - 1 ] + 1 ),所以可以省略 dp[ i - 1 ][ j - 1 ] + 2 的情况。② 替换操作:dp[ i ][ j ] = dp[ i - 1 ][ j - 1 ];无需操作,dp[ i ][ j ] = dp[ i - 1 ][ j - 1 ];① 删除操作:dp[ i ][ j ] = dp[ i - 1 ][ j ];
2023-12-05 18:05:27 513
原创 代码随想录算法训练营第五十五天 | 392.判断子序列,115.不同的子序列
(1)dp[ i ][ j ] 表示 s 前 i 个元素与 t 的前 j 个元素的相同子序列的长度;(4)外层遍历 s 的每个元素,内层遍历 t 的每个元素;(3)设 dp[ 0 ][ 0 ] = 0 为空状态;s 的前 i 个元素的子序列中出现。(1)dp[ i ][ j ] 表示。(4)外层遍历 s,内层遍历 t;t 的前 j 个元素的。115.不同的子序列。
2023-12-04 12:00:53 388
原创 代码随想录算法训练营第五十三天 | 1143.最长公共子序列,1035.不相交的线,53. 最大子序和 动态规划
实际上,上一题中的公共子序列得到的两个字符串中相对位置是有顺序的,所有按照公共子序列进行连线并不会相交,所以本题实质上和上一题是一模一样的,只需要改变量名即可。(1)dp[ i ][ j ] 表示 text1 前 i 个元素、text2 前 j 个元素的最长公共子序列的长度;(3)dp[ 0 ][ 0 ]设为空状态,dp[ i ][ j ] = 0;(1)dp[ i ] 表示以第 i 个元素结尾的数组的和;(4)外层遍历 text1,内层遍历 text2;1143.最长公共子序列。被题目复杂的表面吓到了。
2023-12-03 18:22:27 346
原创 代码随想录算法训练营第五十二天 | 300.最长递增子序列,674. 最长连续递增序列,718. 最长重复子数组
(1)dp[ i ][ j ] 表示以 nums1 的第 i 个元素、nums2 的第 j 个元素为结尾的重复子数组的长度;(1)dp[ i ] 表示以第 i 个元素为结尾的递归子序列的长度;(4)外层循环遍历每个元素,内层循环从头开始遍历到外层元素;(4)外层遍历 nums1,内层遍历 nums2;674. 最长连续递增序列。718. 最长重复子数组。300.最长递增子序列。
2023-12-03 17:34:32 542
原创 代码随想录算法训练营第五十一天 | 309.最佳买卖股票时机含冷冻期,714.买卖股票的最佳时机含手续费,股票总结
(2)dp[ i ][ 0 ] 有三种情况:① 第 i - 1 天持有;② 第 i - 1 天是卖出状态(今天买入);dp[ i ][ 1 ] 有两种状态:① 第 i - 1 天是卖出状态(以前就卖出);② 第 i - 1 天是冷冻期(前天刚卖出);dp[ i ][ 2 ] 有一种状态:① 第 i - 1 天持有股票(今天卖出);dp[ i ][ 3 ] 有一种状态:① 第 i - 1 天卖出;(1)dp[ i ][ j ] 表示第 i 天的所拥有的钱,j 表示状态;1. 不持有股票——卖出状态。
2023-12-01 22:25:04 446
原创 代码随想录算法训练营第五十天 | 123.买卖股票的最佳时机III,188.买卖股票的最佳时机IV
在买卖股票的最佳时机 Ⅰ、Ⅲ中,我们使用二维的 dp数组,其中第二维用于表示当前状态, 当只能买卖一次时有两种状态,当能买卖两次时有4种状态,拓展一下, 当能买卖 k 次时,可以有 2k 种状态,并且每种状态之间的关联都是相通的。为了保持统一,特地在所有状态前加入了 0 状态,表示不进行操作,随后是 1 到 2k 个状态。dp[ i ][ 1 ] 表示第一次不持有股票;dp[ i ][ 3 ] 表示第二次不持有股票;(1)dp[ i ][ 0 ] 表示第一次持有股票;123.买卖股票的最佳时机III。
2023-12-01 16:11:42 386
原创 代码随想录算法训练营第四十九天 | 121. 买卖股票的最佳时机,122.买卖股票的最佳时机II
dp[ i ][ 1 ] 表示第 i 天不持有股票时,手上的最大金额;初始手上金额为 0,持有股票说明当前已经买入了股票,则手上金额为负;(1)dp[ i ][ 0 ] 表示第 i 天持有股票时,手上的最大金额;比较好想到的是贪心算法,贪心选择价格更低的日子买入,价格更高的日子卖出。(1)dp[ i ] 表示前 i 天能得到的最大利润;贪心算法之前做过了;122.买卖股票的最佳时机II。121. 买卖股票的最佳时机。
2023-11-29 16:28:25 468
原创 代码随想录算法训练营第四十八天 | 198.打家劫舍,213.打家劫舍II,337.打家劫舍III
第一反应是,可以将偷取方式分为两部分:从 1 到 n-1、从 2 到 n,然后进行比较。(1)dp[ i ] 表示经过前 i 户所偷的最高金额,且偷第 i 户;本题应当使用后序遍历,将子树的情况汇总到父节点,判断父节点是否偷取。dp0 表示本节点不偷取,dp1 表示本节点偷取;1. 左孩子偷取,右孩子不偷取;2. 左孩子不偷取,右孩子偷取;3. 左孩子偷取,右孩子偷取;4.左孩子不偷取,右孩子不偷取;(4)从小到大遍历房屋;337.打家劫舍III。213.打家劫舍II。
2023-11-28 11:16:05 392
原创 代码随想录算法训练营第四十六天 | 139.单词拆分,多重背包,背包问题总结
循环顺序:(1)组合问题:外层遍历物品、内层从小到大遍历背包容量;(2)排列问题:外层遍历背包容量,内层遍历物品。不要求字典中的单词全部使用,但是要求拆分的单词拆分成的每一个子串都是字典中的单词。(1)dp[ i ] 表示前 i 个字符组成的字符串可以被字典中的单词拆分;多重背包中,将 物品的数量 转化为 数量个相同的物品,转化成 01背包问题;物品数量为 1,循环顺序:外层遍历物品、内层从大到小遍历背包容量。(4)强调子串顺序,外层遍历背包,内层遍历物品;C++ 实现中时在循环中遍历数量。
2023-11-26 14:32:07 643
原创 代码随想录算法训练营第四十五天 | 70. 爬楼梯 (进阶),322. 零钱兑换,279.完全平方数
要求的是凑成所需金额所需要的最少钱币数,所以 dp数组的值就设为凑成当前金额所需的最少钱币数。(3)由于每次更新是求最小值,所以初始化时,将钱币金额设为 1,其余设为 INT_MAX;(3)能用一个数的完全平方表示的初始化为 1,其余初始化为 INT_MAX;之前的爬楼梯用贪心算法,递归实现了;(1)dp[ i ] 表示凑出 i 金额所需的最少钱币数;(4)属于组合问题,外层遍历物品,内层从小到大遍历背包;(4)组合问题,外层遍历物品,内层从小到大遍历背包容量;的完全平方数的最少数量;
2023-11-24 14:51:37 368
原创 代码随想录算法训练营第四十四天 | 完全背包,518. 零钱兑换 II,377. 组合总和 Ⅳ
之所以有 dp[i] < INT_MAX-dp[i-nums[j]] 这样一条判断,是因为 C++的测试用例中有出现某个 dp 值超过 int 范围的情况,但因为题目说保证答案符合 32 位整数范围,所以这个超范围的情况一定对最终结果没有影响,所以我们就不必在意他的 dp 值是否更新了。2. 完全背包的两层循环:物品、背包容量,嵌套顺序可以互换;需要注意的是,外层循环为背包容量时,dp数组的更新需要判断背包是否能容纳当前物品。完全背包是从小到大。(4)求排列数,外层循环遍历背包,内层循环遍历物品;
2023-11-23 15:29:00 34
原创 代码随想录算法训练营第四十三天 | 1049. 最后一块石头的重量 II,494. 目标和,474.一和零
两块石头相撞,就是模拟两数相减的过程,要使所有石头相撞完以后剩余最小,需要让所有相撞的石头的重量差最小,整体来看,就是将这一堆石头分成尽可能重量相近的两堆,这就与昨天的 分割等和子集 联系起来了。其实遍历顺序我总感觉有问题,或者说是想不通,只是因为 01背包问题的模板就是这样的,所以我也这么写,没想到还是对的,突然感觉这个过程有点玄幻,回头还得好好顺着逻辑模拟分析一遍流程。因为每个数只能被用一次,所以还是 01背包 问题,不同的是求的是有多少种实现方法,所以 dp数组 表示装满背包有多少种方法;
2023-11-22 17:59:41 37
原创 代码随想录算法训练营第四十二天 | 01背包问题,416. 分割等和子集
这题既然与 01背包问题安排在同一天,说明是同一个思路;分割成两个等和的子集,这个和到底是多少,我们是知道的,利用动态规划的思想,每次判断该数是不是要取,关键就是 dp 数组代表什么。既然是 01背包问题,那么 dp数组 代表背包当前的容量。经典题目了,印象比较深,需要注意的就是 dp 数组的初始化;2. 遍历背包容量时要求,必须倒序,且必须大于物品大小;1. 遍历顺序要求,必须先遍历物品,再遍历背包容量;416. 分割等和子集。
2023-11-21 13:41:30 141
原创 代码随想录算法训练营第四十一天 | 343. 整数拆分,96.不同的二叉搜索树
若 1 为根节点,则 2—n 在右子树,右子树的情况与求 n - 1 个节点的情况一致,即dp[ n ] += dp[ n - 1 ];dp[ i ] = dp[ i - j ] * dp [ j ],但是一个数经过拆分后的乘积未必大于其本身,所以应当是dp[ i ] =若 2 为根节点,则 1 在左子树,3—n 在右子树,dp[ n ] += dp[ 1 ] * dp[ n - 2 ];若 i 为根节点,则 dp [ n ] += dp[ i - 1 ] * dp[ n - i ];
2023-11-20 17:18:22 62
原创 代码随想录算法训练营第三十九天 | 62.不同路径,63. 不同路径 II
比较上一题,图中间多了障碍物,也就是说障碍物的右边和下边的格子不能从经由障碍的路径到达,如果障碍物在边路,则边路更远的地方则无法到达;此外,其余逻辑不变。(1)dp[ i ][ j ] 表示到达第 i 行 j 列共有多少种不同的路径;(4)i 从 1 到 m 遍历,j 从 1 到 n 遍历;63. 不同路径 II。很明显的动态规划题目。
2023-11-18 16:07:27 688
原创 代码随想录算法训练营第三十八天 | 理论基础,509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯
上一题是楼梯从上往下看,从剩 1、2 级台阶到剩 n 级台阶;本题是从底往上看,记录爬 i 层所需要的最小花费,直到第 n 层。(1)dp[ i ] 表示第 i 层向上爬的花费,包括本层向上爬的花费 + 爬到本层所需要的最小花费;这一题与上一题逻辑完全一样,代码上作下改进,(4)遍历顺序从 2 到 n;746. 使用最小花费爬楼梯。509. 斐波那契数。
2023-11-17 16:05:47 49
原创 代码随想录算法训练营第三十七天 | 738.单调递增的数字,968.监控二叉树
分析下情况,如果当前节点没有被监控,若其有孩子,则可以在其孩子处设一个监控,则当前节点、监控处的节点、监控的所有孩子都被监控;(3)中间逻辑:每当遍历到当前节点时,都要确保能够被监控:孩子有监控——当前节点被监控且不用设置监控、孩子没有监控——当前节点需要设置监控。但是我想了一下,如果从顶向下遍历,孩子有可能在左或者在右,不好判断监控放在哪一边可以使监控数量更少;一旦出现当前数字比前一个数字大的情况,就可以将前一个数字(如有多个相同数字,则改排在最前的那一个)缩小 1,并将后面所有数字变为 9。
2023-11-16 17:38:02 30
原创 代码随想录算法训练营第三十六天 | 435. 无重叠区间,763.划分字母区间,56. 合并区间
偷偷看了眼提示,可以设立一个表用于记录该字母最后一次出现的位置;每次划分区间时判断是否区间内所有字母的最后一次出现的位置在区间内。每个字母只能出现在同一个区间中,难点在于如何确保划分区间之后的部分不会再出现该字母;与昨天用最少的箭引爆气球类似,先将区间按左或右区间排序,然后分析重叠情况。与前面设计的重叠区间类似,先将区间排序,然后判断重叠,有重叠就合并。435. 无重叠区间。763.划分字母区间。
2023-11-15 19:16:38 32
原创 代码随想录算法训练营第三十五天 | 860.柠檬水找零,406.根据身高重建队列,452. 用最少数量的箭引爆气球
重新排队,先排高的,前面有多少比自己高的,就意味着当前队伍中自己该排在哪里,后排的矮个子如果插入队中,也不会改变排队逻辑。若当前组的气球与下一个气球不存在重叠区间,则需要增加一只箭才能引爆下一气球。若当前组的气球与下一个气球存在重叠区间,则一定能在一箭内一起引爆;设两个变量,用于记录 5 元、10 元零钱的数量,每次根据不同情况判断能否找零。感觉这题有点困难,没有明白题目内涵;查看了解析以后明白了。vector的添加比较费时,可以改成使用链表。若气球数不为 0,一定会用至少一只箭;若气球数为 0,不用箭;
2023-11-14 20:16:19 29
原创 代码随想录算法训练营第三十四天 | 1005.K次取反后最大化的数组和,134. 加油站,135. 分发糖果
首先每个孩子分得一个,然后从左向右看,如果右孩子比左孩子评分高,就给右孩子比左孩子多一个糖果;然后从右向左类似,如果左孩子比右孩子评分高,但是现在左孩子并没有比右孩子的糖果多,就给左孩子比右孩子多一个糖果。路线是下标连续的,需要按顺序走;所以可以先从 0 开始计算,若到某一处油不够,说明这中间都不能作为起点,因为一定会油不够,所以后面应该为起点,从后继续计算。若没有 0,将最小的正数取反,即绝对值最小的数取反;(1)存在负数:将最小的负数,即绝对值最大的负数取反;(2)没有负数:若有 0,将 0 取反;
2023-11-13 19:39:06 50
原创 代码随想录算法训练营第三十二天 | 122.买卖股票的最佳时机II,55. 跳跃游戏,45.跳跃游戏II
122.买卖股票的最佳时机II按照一般思路,应该是低买高卖,但实际上“昨天买明天卖”和“昨天买今天卖 然后 今天再买明天卖”的效果上是一样的;采用贪心算法,只要第二天的价格高于前一天,就在前一天买第二天卖出。55. 跳跃游戏思路1每次跳跃元素数个长度,最终希望到达最后一个下标;从尾向前看,倒数第二个元素必须大于等于 1,才能到达最后一个下标处;如果倒数第二个元素大于等于 1,也就是说之前的元素只要能跳跃到倒数第二个元素,就一定能到最后一个下标处;
2023-11-11 15:15:48 32
原创 代码随想录算法训练营第三十一天 | 理论基础,455.分发饼干,376. 摆动序列,53. 最大子序和
理论基础贪心算法没有固定套路,难点在于通过局部最优,推出整体最优;可以手动模拟一下,如果可行就用贪心算法;如果不可行,可能就需要动态规划;至于如何验证贪心是否正确?可自行试举反例,主要还是多积累经验。。455.分发饼干先将饼干和孩子胃口排序,从小饼干和小胃口孩子开始,尽可能满足多的孩子。376. 摆动序列动态规划这道题目第一反应就是动态规划,没有想到贪心算法该如何贪心。
2023-11-10 19:00:24 30
原创 代码随想录算法训练营第三十天 | 332.重新安排行程,51. N皇后,37. 解数独
查看解析以后,发现是用 map 映射实现,一个出发机场可能映射多个降落机场,多个降落机场按字典序排列,所以用 unordered_map 记录映射,用 map 来实现降落机场的排序、记录该次航班是否已经被遍历过;否则,摆下本行棋子,遍历本行所有空位,若满足不同列、不同对角,即可摆放,然后再继续递归摆下一行;(4)切割问题类似组合问题,组合每次进行取数操作,切割每次进行划分操作,每次遍历决定切割线的位置;(5)子集问题中要注意的是,收集每个节点的结果,因为每个结果对应的都是一种子集;
2023-11-10 14:17:08 32
原创 代码随想录算法训练营第二十九天 | 491.递增子序列,46.全排列,47.全排列 II
全排列同层不需要去重,但是同支需要去重,有了上一题的经验,我们还是选择新建集合用于记录数字是否已被选从而实现去重;与上一题不一样的是,上一题是同层去重,集合定义在回溯函数中,而本题是同支去重,集合需要定义在全局。这题的去重逻辑几乎和上一题是一样的,但是区别在于,本题所给序列中有重复数字,去重时不能根据数值判断,应该根据数字在序列中的下标判断。与子集不同的是,这里是子序列,不能排序处理原数组;很快就遇到了第二个问题,当序列中有重复数字时如何去重,即同层去重,考虑到今天第一题,再在同层设置集合用于去重。
2023-11-09 11:39:17 36
原创 代码随想录算法训练营第二十四天 | 理论基础,77. 组合
按照回溯模板能轻松写出上述代码,但是时间和内存的情况让我有点难绷,不过看了下解析也是这个思路,想来回溯的本质是穷举,效率本就不高,那就不改了。(3)回溯逻辑:设定组合中的元素是升序的,已经组合的数组中元素已定,回溯确定下一位的元素数值;与递归类似,区别在于中间逻辑中,处理节点后进行递归以后,要进行回溯,撤销处理的结果,(1)参数:已经组合的数组,总共需要组合的元素数量;(2)终止条件:已经组合的数组中元素已足够数量,将该数组加入结果中;组合类型的题目是回溯的经典题型,使用回溯法解决;
2023-11-05 15:05:18 34
原创 代码随想录算法训练营第二十三天 | 669. 修剪二叉搜索树,108.将有序数组转换为二叉搜索树,538.把二叉搜索树转换为累加树
669. 修剪二叉搜索树。
2023-11-04 20:42:53 63 1
原创 代码随想录算法训练营第二十二天 | 235. 二叉搜索树的最近公共祖先,701.二叉搜索树中的插入操作,450.删除二叉搜索树中的节点
235. 二叉搜索树的最近公共祖先。
2023-11-02 17:10:57 33
原创 代码随想录算法训练营第二十一天 | 530.二叉搜索树的最小绝对差,501.二叉搜索树中的众数,236. 二叉树的最近公共祖先
236. 二叉树的最近公共祖先530.二叉搜索树的最小绝对差。
2023-11-02 10:33:03 62
原创 代码随想录算法训练营第二十天 | 654.最大二叉树,617.合并二叉树,700.二叉搜索树中的搜索,98.验证二叉搜索树
或者可以在中序遍历中确定当前结点的值是否大于前一个遍历的数值,毕竟二叉搜索树的中序遍历本来就是从小到大的;单独记录前一个遍历的结点,因为如果只是记录数值的话,后台测试数据有int最小值,尽量避免初始化最小值;我的第一思路是就直接看结点,要求左孩子小于中结点,右孩子大于中结点;但是正如解析中的那样,我犯了经典的错误,因为这种大小限制不具有持续性,因为二叉搜索树要求结点的左子树全部结点都比自己小,右子树都比自己大。所以还是先中序遍历,再判断有序性;700.二叉搜索树中的搜索。98.验证二叉搜索树。
2023-10-31 18:55:19 73 2
原创 代码随想录算法训练营第十八天 | 513.找树左下角的值,112. 路径总和 113.路径总和ii, 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树
513.找树左下角的值。
2023-10-30 09:42:10 57 1
原创 代码随想录算法训练营第十七天 | 110.平衡二叉树,257. 二叉树的所有路径,404.左叶子之和
过程逻辑:某一结点的左右子树高度差若超过 1,则没必要继续求高度差了,整棵树已然不是平衡二叉树,返回 -1 以说明不平衡;最简单的就是遍历各个结点,判断其是不是叶子结点,递归时比平常的遍历递归多一个孩子类型参数,说明是其父结点的左孩子还是右孩子。感觉可以用两个栈,一个用来存结点,一个用来存对应结点的类型(左孩子 or 右孩子)拿到题目首先想到了递归法,每次递归得到各结点左子树与右子树的高度差;代码随想录的讲解今天来不及看了,先写了自己的版本,后面有时间补看下。返回值:高度(差);终止条件:结点为空;
2023-10-27 20:47:07 61 1
原创 代码随想录算法训练营第十六天 | 104.二叉树的最大深度、559.n叉树的最大深度,111.二叉树的最小深度,222.完全二叉树的节点个数
104.二叉树的最大深度 559.n叉树的最大深度。
2023-10-26 18:08:43 39 1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人