- 博客(54)
- 资源 (1)
- 收藏
- 关注
原创 代码随想录一刷总结
课程框架比较合理,从基础的数据结构到回溯、动态规划、图论算法,由浅入深、循序渐进,一刷下来,不论是底层的编码能力,还是算法层的逻辑思维能力,都得到很好的打磨。说实话,后面图论的题目基本是照猫画虎,半抄半写,理解的其实还不是特别深入,后面有机会再二刷、三刷吧!
2024-10-22 21:28:00
231
1
原创 代码随想录训练营第65天|bellman_ford应用
用visited数组记录已经在队列里的元素,已经在队列的元素不用重复加入。比上题多松弛一次,看minDist数组 是否发生变化。
2024-10-22 20:02:23
328
原创 代码随想录训练营第60天|冗余连接
已在同一个集合的,如果继续连接,则成环,即是题目所求。确定图中一定有了有向环,那么要找到需要删除的那条边。判断删一个边之后是不是有向树。
2024-10-12 10:00:00
740
原创 代码随想录训练营第58天|统计相邻
采用广搜,第一次找到的一定就是最短的。寻找方式:遍历所有位置、所有可能得字符,得到的newWord必须在候选集中,同时之前没有被访问过,才会加入队列,进行下一层的搜索。本题不需dfs,只要求出相邻陆地个数即可,对每个新陆地只考虑左上是否存在相邻,右下的相邻可以归属到下一个陆地的左上方,以此避免重复计算。通过深搜更新标记数组visited,对于未访问过的key才会调用dfs,进入函数后首先就进行标记。
2024-10-10 17:30:58
867
原创 代码随想录训练营第57天|逆向思维
题目要求顺流而下,能同时到达一和二边界的点,逆向思维,等价于从一和二出发,逆流而上,二者覆盖的交集即为所求。利用firstBorder,secondBorder作为标记数组,采用深搜,标记每个边界出发所能覆盖的范围。接着,尝试可能的0点,累加与其相邻的岛屿面积(这里注意用set去重,加过的岛屿不再累计),对所有可能得方案取最大。先将四个边扫一圈,相邻的清0,然后对内圈元素开始深搜计数,此时得到的面积都属于孤岛。和上题思路差不多,扫外圈的时候做特殊标记,再“沉没”的时候再根据标记恢复现场。
2024-10-09 20:13:47
456
原创 代码随想录训练营第56天|广度优先搜索
用全局变量,累计单个岛屿面积。主程序里用result选出最大。深搜,首次访问到时计数,并将相邻元素清零,避免重复统计。广搜,每次向队列中push一圈元素,不断向外膨胀。
2024-10-09 17:03:20
369
原创 代码随想录训练营第54天|单调栈+双指针
选定heights[i]作为中心,向两边膨胀得到最大面积,当遇到第一个比它小的元素时,则不可继续膨胀(否则会以更小的这个元素为中心,而不是heights[i]),也就是问题转化为求【下一个更小元素】的问题,参考上一篇博客,经典的单调栈解法。按列统计雨水容量,每列可装的雨水高度:min(max_left[i],max_right[i])-height[i]max_right[i]:第i个元素以右(包含第i个),所有元素的最大值。max_left[i]:第i个元素以左(包含第i个),所有元素的最大值。
2024-10-06 17:00:38
492
原创 代码随想录训练营第48天|单调栈
单调栈的核心思想是利用while循环批量处理栈顶元素,使剩下的栈内元素保持单调。和上题基本一致,利用value_idx构造结果。单调栈存的是索引,返回值记录的也是索引间隔。和1题基本一致,用拼接的方式实现伪循环。
2024-10-06 11:03:18
595
原创 代码随想录训练营第46天|回文子序列
贪心解法,由中心向两边扩散,直至不相等,得到最大回文串。遍历所有可能的中心,累计扩散过程所有的子串。利用最长子序列解决回文子序列问题。
2024-09-28 21:02:47
389
原创 代码随想录训练营第45天|编辑距离
1.若结尾不等,则s[i]无法发挥作用,只能由i-1前的子串构建,个数等同于dp[i-1][j]dp[i][j]:截止到s[i],t[j](包含)的两个子串所形成的子序列个数。dp[i][j]:由word1[0:i]到word2[0:j]的最小删除操作数目。dp[i][j]:由word1[0:i]到word2[0:j]的编辑距离。1.若结尾相等,则不会增加编辑距离,由dp[i-1][j-1]转移而来。1.若结尾相等,则不会增加操作数,由dp[i-1][j-1]转移而来。
2024-09-28 20:15:47
615
原创 代码随想录训练营第44天|最长公共子序列
2.若二者不等,则至少有一个元素在子序列的构建中被剔除,可能剔除text1的末尾,则此时由dp[i-1][j]转移而来,或者text2的末尾,则由dp[i][j-1]转移而来。加入虚拟头简化dp初始化,定义dp[i][j]:截止到text1[i]及text2[j],两个子串所能形成的最长子序列长度。1.若text1[i]==text2[j]:则此时最长子序列可由dp[i-1][j-1],加上相等的这一个,转移而来。定义dp[i]:截止到nums[i](包含)的最大子数组和。取两种情况的较大值。
2024-09-27 11:41:25
541
原创 代码随想录训练营第43天|二维dp
转移方程:可由前置的任何一个j转移而来(满足递增的情况下),累计最大得到dp[i],对所有dp取最大值得到全局最大,注意最长递增子序列不一定要取到末尾元素,可能在中间最大。两个输入,二维dp,定义dp[i][j]:使用nums1[i]及nums2[j]结尾的重复子数组的最大长度。和上题的差异在“连续”,意味着只能从上一个元素(i-1)转移而来,而不用遍历所有前置节点。1.如果结尾元素相等,则可由删除结尾的子串的最长重复子数组转移而来。dp[i]:以下标i为终点的递增子序列的最大长度。
2024-09-25 09:46:34
302
原创 代码随想录训练营第42天|k状态转移
参考前一天2次买卖的题目,思路是一样的,k次买卖存在的状态1(不操作)+k*2(买或卖)2.由前置的一个状态转移而来。1.保持上一天的同状态。
2024-09-24 21:16:39
216
原创 代码随想录训练营第41天|状态转移
遍历所有可能的卖出点,跟历史最低价格比,算当前利润,得到全局最优。历史低价要动态更新。dp[i][j]表示第i天状态j所剩最大现金。利润是可以分解的,累计所有正盈利的单天,即为最大收益。2.操作,按以下顺序:0->1->2->3->4。1.不操作,保留上一天同状态。2.第一次不持有股票。4.第二次不持有股票。
2024-09-23 11:38:55
357
原创 代码随想录训练营第39天|树形dp
采用后续遍历,利用子树的结果构建当前结果,也是分治的思想,即把当前问题拆解为规模更小的子问题,直到空树,一定为{0,0}。状态转移:定义rob_tree返回的是pair:{不抢根的最大值,抢根的最大值}上题的变种,题目可以拆分为两种情况:抢第一间或不抢第一间。dp[i]:截止下标i(包含i)的房子,所能打劫的最大金额。引入空房间作为虚拟头,初始化更简单,且不影响最终结果。
2024-09-21 10:49:56
562
原创 代码随想录训练营第38天|string虚拟头
转移方程:尝试所有可能得语料wordDict,使用双指针确认子串尾部是否可由指定word构成,如果可以,则此时dp[i]就取决于dp[i-word.length()],只要找到一个凑成的模式,就可以提前结束内层循环。转移方程:给定coin,若使用,则意味着使用之前已凑够i-coin,此时最小硬币数为:dp[i-coin]+1,遍历所有可能的coin取最小。转移方程:给定i*i,若使用,则意味着使用之前已凑够j-i*i,此时最小硬币数为:dp[j-i*i]+1,遍历所有可能的i取最小。
2024-09-20 17:22:41
1100
1
原创 代码随想录训练营第37天|背包排列数
由于物品遍历是有序的,在使用靠前的物品时,是无法利用靠后物品的信息的。在使用零钱1刷新滚动数组时,是不知4的存在的,此时统计的方案数也绝对不会出现(1,4),只有当遍历到零钱4时,才会将(4,1)的情况计入。给定面额coin,如果使用它后凑到金额i,意味着使用之前已凑够i-coin,对应的方案数为dp[i-coin],累加所有可能得到dp[i]。转移方程:假设是移动j(按题意1
2024-09-19 16:34:07
513
原创 代码随想录训练营第36天|二维背包
转移方程:尝试用所有str刷新“滚动数组”,先统计该str的01分布,使用该str,则dp[i][j]将由dp[i-zero_num][j-one_num]转移而来,累计最大值。表示dp[i]可由任一个num转移而来,则要求转移前的和为i-num,对应的方案数dp[i-num],累加所有的可能得到总的方案数。初始化dp[0]=1,表示和为0的方案数为1,即空集:一个都不选也是一种方案。dp[i][j]:0最大i个,1最大j个的最大子集中的元素数目。转移方程:dp[i]+=dp[i-num];
2024-09-18 17:54:30
375
原创 代码随想录训练营第35天|逆序背包
另外一个细节,背包容量需要逆序遍历,这样对推过程中利用的dp[i-weights[j]]均是不考虑values[j]的最优解,也即每个物品只能使用一次。用不同的物品刷新"滚动数组",每一个新的物品会占据空间weights[j],并带来价值values[j],所以得到新的价值:dp[i-weights[j]]+values[j], dp[i]累计所有可能的最大值。状态转移方程:dp[i]=max(dp[i],dp[i-weights[j]]+values[j]);贪心解法,从中心向两边扩散,得到回文长度。
2024-09-17 12:40:18
336
原创 代码随想录训练营第34天|dp前置转移
转移方程:给定节点数i,搜索树的根可以取1、2……i,dp[i]累加不同情况而来。另外,dp[1]初始化为0,表示拆分1的情况是非法的,这样取max后自然被过滤掉。转移方程:可由上/左两个方向转移而来,累加不同的方案数。dp[i]:给定节点数i,可构造的搜索树数目。dp[i][j]:运动至(i,j)的方案数。dp[i][j]:运动至(i,j)的方案数。dp[i]:拆分i可以达到的最大乘积。根据dp的定义对二者取最大。
2024-09-16 12:57:37
1015
原创 代码随想录训练营第32天|dp边界
dp[i]:爬到下标为i的楼梯所需要的最小花费,可能由两种情况转移而来:i-1层跨一步,或i-2层跨两步。因为要求的是最小花费,所以要对所有的可能取min。dp[i]: 爬到第i层的方案数,可能由两种情况转移而来:i-1层跨一步,或i-2层跨两步。因为要求的是方案数,所以要累加所有的可能。
2024-09-14 09:14:03
309
原创 代码随想录训练营第30天|区间贪心
先用map将每个字符最远出现的位置存下来,遍历过程更新当前子串最远覆盖距离max_idx,当max_idx恰好等于i时,表明可以作为一个切割点。按起点排序,依次处理,当新区间的起点小于上一个区间的终点时,可以复用,此时要将本区间的终点和上个区间的终点比较,取较小。贪心思想,如果再大,必然有一个区间无法被引爆。另外,vector的erase操作要进行全部元素的搬移,时间复杂度较高,所以采用修改的办法代替删除操作。移除最少<=>保留最多,贪心的思想,保留的区间终点应该越小越好,这样留给后面的空间越大。
2024-09-12 12:11:03
551
原创 代码随想录训练营第29天|控制变量
cur用来累计新的起点下,所有油站的净利, 如果累计到i【首次】出现负值,则符合要求的起点一定在i后面。反证法:假设i之前存在一个符合题意的起点j(old_start
2024-09-11 13:45:08
907
原创 代码随想录训练营第28天|利润分解
第1步处理后,i指向原始数组(排序后)的第一个非负数,在原始数组中已然最小,但考虑到操作1同时会生成新的正数,甚至小于nums[i],所以nums[i-1]也要加入候选,修改较小的元素。在可达范围内(max_range)步进,每次移动后尝试更新max_range,直到所有元素被处理完,此时如果max_range仍未覆盖终点,说明终点不可达,返回false。1.先对nums排序,对于负数,排在越前的,绝对值越大,越要优先反号,带来的收益最大。dp[i]表示跳跃至下标为i的位置所需的最小步数。
2024-09-10 10:58:30
442
原创 代码随想录训练营第25天|set去重
nums不能排序,所以无法用while在回溯后去重,只能借助set,记录当前层已经使用过的数值,通过count方法实现去重。排列需要考虑顺序,不能用startIdx递增搜索,通过标记数组used,搜索每一层未使用过的元素。本题nums可以进行排序,所以回溯后利用while过滤掉相同数值,即可实现去重。
2024-09-07 10:24:17
311
原创 代码随想录训练营第24天|回溯过程收集
ip最多4段,所以根据path.size()终止回溯,此时如果字符串被切割到末尾,则是一个有效的分割。另外,每一段最大255,所以子串长度最大为3,据此可以进行剪枝。遍历的过程收集结果即可。
2024-09-07 09:06:03
289
原创 代码随想录训练营第23天|回溯去重
因为可以重复选取,所以递归的下一个数字的搜索起点(startIdx)是i,而非i+1。回溯之后,相同数值的元素直接跳过,实现本层去重功能。
2024-09-05 11:04:43
323
原创 代码随想录训练营第22天|回溯剪枝
减枝策略:i不能太大,否则无法凑够k个元素,当前已收集元素个数:path.size(),待收集个数:k-path.size(),终点最大为(开区间): n+1,得到起点最大:n+1-(k-path.size())。剪枝策略:i不能太大,考虑两个限制:1.满足组合个数要求,如果i太大,无法凑到k个元素 2.满足求和要求,如果i太大,当前层已经突破了n,因为i是递增的(i++),所以后续的遍历都是无效的。
2024-09-04 08:57:59
236
原创 代码随想录训练营第21天|搜索树修剪前后序
题目要求累加>=root的值,结合搜索树中序(左->根->右)递增的特性,这里所以采用右->根->左的遍历方式,同时利用pre指针指向前置节点,实现前缀和的计算。解法一:修剪根节点,不能直接返回nullptr,因为子树仍可能存在符合要求的节点。考虑搜索树的特性,只需要对一个方向的子树递归即可。搜索树特性:中序遍历递增,即左
2024-09-03 12:06:05
192
原创 代码随想录训练营第20天|带返回值的递归
待查询的节点本身也需进path,解决p就是q的父节点的case。利用递归返回值,完成父子关系的绑定:下一层加入节点返回新树,本层用root->left或者root->right将其接住。
2024-09-02 11:50:53
233
matlab与C++混编教程
2016-03-07
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人