- 博客(36)
- 收藏
- 关注
原创 第十章 单调栈part01 739. 每日温度 496.下一个更大元素 I 503.下一个更大元素II
题目说如果不存在对应位置就输出 -1 ,所以result数组如果某位置没有被赋值,那么就应该是是-1,所以就初始化为-1。在遍历nums2的过程中,我们要判断nums2[i]是否在nums1中出现过,因为最后是要根据nums1元素的下标来更新result数组。
2024-07-11 23:16:56
669
原创 第九章 动态规划part10 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组
674. 最长连续递增序列。718. 最长重复子数组。300.最长递增子序列。
2024-07-07 21:48:47
235
原创 188.买卖股票的最佳时机IV 309.最佳买卖股票时机含冷冻期 714.买卖股票的最佳时机含手续费
714.买卖股票的最佳时机含手续费。309.最佳买卖股票时机含冷冻期。在旅游笔记本屏幕太小了,回去补。188.买卖股票的最佳时机IV。
2024-07-07 21:46:40
266
原创 day 43 任务以及具体安排:第九章 动态规划part08
如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。从dp[i]的定义上来讲,dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
2024-07-04 00:09:43
986
原创 day 41 322. 零钱兑换 279.完全平方数 139.单词拆分
凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。
2024-07-02 17:41:10
724
原创 day 38 1049. 最后一块石头的重量 II 494. 目标和 474.一和零
1049本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,。是不是感觉和昨天讲解的非常像了。本题物品的重量为stones[i],物品的价值也为stones[i]。对应着01背包里的物品重量weight[i]和 物品价值value[i]。。可以回忆一下01背包中,dp[j]的含义,容量为j的背包,最多可以装的价值为 dp[j]。
2024-06-30 21:27:34
981
原创 第九章 动态规划part01 509. 斐波那契数70. 爬楼梯746. 使用最小花费爬楼梯
斐波那契数列大家应该非常熟悉不过了,非常适合作为动规第一道题目来练练手。因为这道题目比较简单,可能一些同学并不需要做什么分析,直接顺手一写就过了。但「代码随想录」的风格是:简单题目是用来加深对解题方法论的理解的。通过这道题目让大家可以初步认识到,按照动规五部曲是如何解题的。对于动规,如果没有方法论的话,可能简单题目可以顺手一写就过,难一点就不知道如何下手了。所以我总结的动规五部曲,是要用来贯穿整个动态规划系列的,就像之前讲过二叉树系列的递归三部曲 (opens new window),回溯法系列的回溯三部曲
2024-06-27 17:22:33
1170
原创 day 33 452. 用最少数量的箭引爆气球 435. 无重叠区间 763.划分字母区间
此时问题就是要求非交叉区间的最大个数。这里记录非交叉区间的个数还是有技巧的,如图:区间,1,2,3,4,5,6都按照右边界排好序。当确定区间 1 和 区间2 重叠后,如何确定是否与 区间3 也重贴呢?就是取 区间1 和 区间2 右边界的最小值,因为这个最小值之前的部分一定是 区间1 和区间2 的重合部分,如果这个最小值也触达到区间3,那么说明 区间 1,2,3都是重合的。接下来就是找大于区间1结束位置的区间,是从区间4开始。
2024-06-24 18:00:08
623
原创 Day 31 134. 加油站 135. 分发糖果 860.柠檬水找零 406.根据身高重建队列
情况二:rest[i] = gas[i]-cost[i]为一天剩下的油,i从0开始计算累加到最后一站,如果累加没有出现负数,说明从0出发,油就没有断过,那么0就是起点。情况三:如果累加的最小值是负数,汽车就要从非0节点出发,从后向前,看哪个节点能把这个负数填平,能把这个负数填平的节点就是出发节点。此时局部最优:只要右边评分比左边大,右边的孩子就多一个糖果,全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果。这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边,
2024-06-24 09:43:06
804
原创 Day 30 122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II 1005.K次取反后最大化的数组和
局部最优推出全局最优,找不出反例,试试贪心!如图:i 每次移动只能在 cover 的范围内移动,每移动一个元素,cover 得到该元素数值(新的覆盖范围)的补充,让 i 继续移动下去。而 cover 每次只取 max(该元素数值补充后的范围, cover 本身范围)。如果 cover 大于等于了终点下标,直接 return true 就可以了。
2024-06-22 12:28:40
745
原创 day 29 455.分发饼干 376. 摆动序列 53. 最大子序和
从代码角度上来讲:遍历 nums,从头开始用 count 累积,如果 count 一旦加上 nums[i]变为负数,那么就应该从 nums[i+1]开始从 0 累积 count 了,因为已经变为负数的 count,只会拖累总和。在计算是否有峰值的时候,大家知道遍历的下标 i ,计算 prediff(nums[i] - nums[i-1]) 和 curdiff(nums[i+1] - nums[i]),如果。大尺寸的饼干既可以满足胃口大的孩子也可以满足胃口小的孩子,那么就应该优先满足胃口大的。
2024-06-21 17:59:55
626
原创 Day 28回溯算法 part04 491.递增子序列 46.全排列 47.全排列 II
本题给出的示例,还是一个有序数组 [4, 6, 7, 7],这更容易误导大家按照排序的思路去做了。图中我们对同一树层,前一位(也就是nums[i-1])如果使用过,那么就进行去重。相信这个排列问题就算是让你用for循环暴力把结果搜索出来,这个暴力也不是很好写。而本题求自增子序列,是不能对原数组进行排序的,排完序的数组都是自增子序列了。这又是子集,又是去重,是不是不由自主的想起了刚刚讲过的。中我们是通过排序,再加一个标记数组来达到去重的目的。所讲的为什么回溯法是暴力搜索,效率这么低,还要用它?
2024-06-20 09:46:13
1034
原创 day 26 # 39. 组合总和 40.组合总和II 131.分割回文串
题目中的无限制重复被选取,吓得我赶紧想想 出现0 可咋办,然后看到下面提示:1 <= candidates[i] <= 200,我就放心了。本题和77.组合 (opens new window),216.组合总和III (opens new window)的区别是:本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。本题搜索的过程抽象成树形结构如下: 注意图中叶子节点的返回条件,因为本题没有组合数量要求,仅仅是总和的限制,所以递归没有层数的限制,只要选取的元素总和超过target,
2024-06-17 19:49:36
1108
原创 DAY24 回溯算法part01 77. 组合 216.组合总和III 17.电话号码的字母组合
回溯法也可以叫做回溯搜索法,它是一种搜索的方式。在二叉树系列中,我们已经不止一次,提到了回溯,例如二叉树:以为使用了递归,其实还隐藏着回溯 (opens new window)。回溯是递归的副产品,只要有递归就会有回溯。所以以下讲解中,回溯函数也就是递归函数,指的都是一个函数。
2024-06-16 18:57:55
1220
原创 Day 23 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树
因为是要遍历整棵树,做修改,其实不需要返回值也可以,我们也可以完成修剪(其实就是从二叉树中移除节点)的操作。怎么一想这么麻烦呢。上图中,是符合二叉搜索树的特性吧,如果要这么做的话,是不是本题意义就不大了,所以才强调是平衡二叉搜索树。因为数组大家都知道怎么遍历啊,从后向前,挨个累加就完事了,这换成了二叉搜索树,看起来就别扭了一些是不是。例如 有序数组[-10,-3,0,5,9] 就可以构造成这样的二叉搜索树,如图。删除二叉树节点,增加二叉树节点,都是用递归函数的返回值来完成,这样是比较方便的。
2024-06-14 19:17:53
1166
原创 Day22 #235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点
如图,我们从根节点搜索,第一次遇到 cur节点是数值在[q, p]区间中,即 节点5,此时可以说明 q 和 p 一定分别存在于 节点 5的左子树,和右子树中。将删除节点(元素7)的左孩子放到删除节点(元素7)的右子树的最左面节点(元素8)的左孩子上,就是把5为根节点的子树移到了8的左孩子的位置。此时节点5是不是最近公共祖先?动画中的二叉搜索树中,删除元素7, 那么删除节点(元素7)的左孩子就是5,删除节点(元素7)的右子树的最左面节点是元素8。要删除的节点(元素7)的右孩子(元素9)为新的根节点。
2024-06-14 11:24:34
636
原创 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先
#530二叉搜索树的最小绝对差思路题目中要求在二叉搜索树上任意两节点的差的绝对值的最小值。注意是二叉搜索树,二叉搜索树可是有序的。遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。#递归那么二叉搜索树采用中序遍历,其实就是一个有序数组。在一个有序数组上求两个数最小差值,这是不是就是一道送分题了。最直观的想法,就是把二叉搜索树转换成有序数组,然后遍历一遍数组,就统计出来最小差值了。需要用一个pre节点记录一下cur节
2024-06-13 09:59:33
319
原创 654.最大二叉树 617.合并二叉树 700.二叉搜索树中的搜索 98.验证二叉搜索树
要定义一个longlong的全局变量,用来比较遍历的节点是否有序,因为后台测试数据中有int最小值,所以定义为longlong的类型,初始化为longlong最小值。题目中说了输入的数组大小一定是大于等于1的,所以我们不用考虑小于1的情况,那么当递归遍历的时候,如果传入的数组大小为1,说明遍历到了叶子节点了。那么应该定义一个新的节点,并把这个数组的数值赋给新的节点,然后返回这个节点。其实本题是同样的道理,我们在寻找一个不符合条件的节点,如果没有找到这个节点就遍历了整个树,如果找到不符合的节点了,立刻返回。
2024-06-12 11:35:24
644
原创 代码随想录算法训练营第18天 | 513.找树左下角的值、112. 路径总和、113.路径总和ii、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树
找到。
2024-06-09 16:54:14
1142
原创 【二叉树】110平衡二叉树、257二叉树的所有路径、404左叶子之和
可以理解代码,但是这个:= 赋值这一块还是差点意思。不太明白为啥直接就等于-1了,因为这是递归的精髓,相当于已经跑了一遍了。这道题目要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。在这道题目中将第一次涉及到回溯,因为我们要把路径记录下来,需要回溯来回退一个路径再进入另一个路径。第一次学回溯,这个就是比较绕,题目难度感觉不是简单。代码量跟难度都比较花时间。我们先使用递归的方式,来做前序遍历。开始尝试并理解什么是递归。
2024-06-07 22:10:54
246
原创 代码随想录算法训练营第十六天 | 104.二叉树的最大深度、111. 二叉树的最小深度、222. 完全二叉树的节点个数
我来举一个典型的例子如题:完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。完全二叉树(一)如图:完全二叉树(二)如图:可以看出如果整个树不是满二叉树,就递归其左右孩子,直到遇到满二叉树为止,用公式计算这个子树(满二叉树)的节点数量。
2024-06-05 23:40:04
821
原创 代码随想录算法训练营第15天 |层序遍历、翻转二叉树、对称二叉树
层序遍历。层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。需要借用一个辅助数据结构即队列来实现,使用队列实现二叉树广度优先遍历,动画如下:这样就实现了层序从左到右遍历二叉树。
2024-06-05 15:16:53
391
原创 代码随想录算法训练营第13天 |栈与队列总结 239. 滑动窗口最大值 347.前 K 个高频元素
寻找前k个最大元素流程如图所示:(图中的频率只有三个,所以正好构成一个大小为3的小顶堆,如果频率更多一些,则用这个小顶堆进行扫描)
2024-06-03 12:28:41
824
原创 算法训练Day11 | LeetCode232. 用栈实现队列(模拟);225.用队列实现栈(模拟);20. 有效的括号(栈应用);1047. 删除字符串中的所有相邻重复项(栈应用)
但还有一些技巧,在匹配左括号的时候,右括号先入栈,就只需要比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了!第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false。第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false。那么什么时候说明左括号和右括号全都匹配了呢,就是字符串遍历完之后,栈是空的,就说明全都匹配了。首先要弄清楚,字符串里的括号不匹配有几种情况。
2024-06-01 21:58:23
744
原创 代码随想录算法训练营第十天| 232.用栈实现队列 225. 用队列实现栈
上次学习这块记忆犹新,只要打基础,那天的我肯定是沮丧的,总会是说的时候都懂,写的时候不知道从哪里下手,看看这次会遇到什么“艰难险阻”及时记录下来。在代码实现的时候,会发现pop() 和 peek()两个函数功能类似,代码实现上也是类似的,可以思考一下如何把代码抽象一下。,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。所以用栈实现队列, 和用队列实现栈的思路还是不一样的,这取决于这两个数据结构的性质。今天是打基础的一天,了解队列和栈的实现。
2024-05-31 11:27:20
580
原创 算法训练Day9| LeetCode28. 找出字符串中第一个匹配项的下标(KMP算法
一刷放过自己,KMP看了理论基础,代码实现的视频。跟着文章复习了一遍字符串总结+双指针回顾。
2024-05-30 19:51:03
175
原创 算法训练Day8| LeetCode344. 反转字符串(双指针);541. 反转字符串II(模拟);offer5. 替换空格(双指针后序);151.反转字符串中的单词(综合);off58.左旋字符串
debug 了一晚上,发现s= s.strip() 可加可不加,因为估计python3 里面split() 已经帮助删除前后空白了。对于字符串,我们定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。因为字符串也是一种数组,所以元素在内存中是连续分布,这就决定了反转链表和反转字符串方式上还是有所差异的。那么反转字符串依然是使用双指针的方法,只不过对于字符串的反转,其实要比链表简单一些。这个块的处理会自动通过切片操作来处理,反转剩余的字符。
2024-05-29 21:30:31
665
原创 算法训练Day7| LeetCode454. 四数相加II(Map作哈希表);383.赎金信(数组作哈希表);15.三数之和(双指针);18.四数之和(双指针)
四数之和的双指针解法是两层for循环nums[k] + nums[i]为确定值,依然是循环内有left和right下标作为双指针,找出nums[k] + nums[i] + nums[left] + nums[right] == target的情况,三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3)。双指针法就是将原本暴力O(n^3)的解法,降为O(n^2)的解法,四数之和的双指针解法就是将原本暴力O(n^4)的解法,降为O(n^3)的解法。说到去重,其实主要考虑三个数的去重。
2024-05-28 23:46:47
983
原创 代码随想录算法训练营Day6 | | 242.有效的字母异位词 ,349. 两个数组的交集 , 202. 快乐数 ,1. 两数之和
std::set和std::multiset底层实现都是红黑树,std::unordered_set的底层实现是哈希表, 使用unordered_set 读写效率是最高的,并不需要对数据进行排序,而且还不要让数据重复,所以选择unordered_set。在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。
2024-05-27 23:31:11
662
原创 代码随想录算法训练营Day4 | | 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 , 面试题 02.07. 链表相交
24. 两两交换链表中的节点 - 力扣(LeetCode)
2024-05-26 16:19:29
757
原创 Day2 数组:977.有序数组的平方 209.长度最小的子数组 59.螺旋矩阵Ⅱ
977.有序数组的平方每个数平方之后,排个序2.双指针法由于的存在,负数平方之后可能就会成为最大数,因此数组平方后的就应该在数组的,不是最左边就是最右边,不可能是中间。此时可以考虑双指针法,i指向起始位置,j指向终止位置。定义一个result来装进行平方之后的数组元素。定义一个索引下标,下标的作用:新的数组要从大到小来更新因为每次取的时候都是取了一个(两头向中间取,先取最大,再取次大)。这样的话,更新result数组也要下标由大到小来更新,最后得到的这个result数组才是一个按。
2024-05-23 21:53:35
717
1
原创 代码随想录算法训练营day01| 704. 二分查找、27. 移除元素
假设总共有n个元素,每次查找的区间大小就是n,n/2,n/4,…,n/2^k,其中k就是循环的次数,时间复杂度:时间复杂度的计算并不是计算程序具体运行的时间,而是算法执行语句的次数。要注意return slow 前面的tab 要跑完while出来才return。空间复杂度:空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。n/2^k >= 1(1最坏的情况,即还剩一个元素),因为变量只创建一次,所以空间复杂度为O(1)。可得k=log2n(以2为底,n的对数),
2024-05-22 22:14:47
523
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人