刷题心得
文章平均质量分 88
Java
甜瓜瓜哥
这个作者很懒,什么都没留下…
展开
-
字符串排序
每个字符串至少含有一个数字字符,按如下规则降序排序:(1) 按照字符串中字母字符个数和数字字符个数(字母数字比)的比值大小进行排序。(2) 若两个字符串的字母数字比相同。则按照字符串本身大小进行排序。输入值:[“abc123”,“abc+1234”,“abcabab–1”]返回值:[“abcabab–1”,“abc123”,“abc+1234”]原创 2023-11-02 23:15:42 · 1262 阅读 · 0 评论 -
84.柱状图中最大的矩形
如果数组本身是降序的,例如 [8,6,4,2],在 8 入栈后,6 开始与8 进行比较,此时我们得到 mid(8),rigt(6),但是得不到 left。如果数组本身就是升序的,例如[2,4,6,8],那么入栈之后 都是单调递减,一直都没有走 情况三 计算结果的哪一步,所以最后输出的就是0了。,是遥相呼应的两道题目,建议都要仔细做一做,原理上有很多相同的地方,但细节上又有差异,更可以加深对单调栈的理解!是找每个柱子左右两边第一个大于该柱子高度的柱子,而本题是找每个柱子左右两边第一个小于该柱子的柱子。原创 2023-10-06 21:52:23 · 31 阅读 · 0 评论 -
42.接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。原创 2023-10-06 17:22:09 · 44 阅读 · 0 评论 -
503.下一个更大元素II
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。将两个nums数组拼接在一起,使用单调栈计算出每一个元素的下一个最大值,最后再把结果集即result数组resize到原数组大小就可以了。resize倒是不费时间,是O(1)的操作,但扩充nums数组相当于多了一个O(n)的操作。不过,本题要循环数组了。原创 2023-10-06 16:16:59 · 37 阅读 · 0 评论 -
496.下一个更大元素 I
题目说如果不存在对应位置就输出 -1 ,所以result数组如果某位置没有被赋值,那么就应该是是-1,所以就初始化为-1。在遍历nums2的过程中,我们要判断nums2[i]是否在nums1中出现过,因为最后是要根据nums1元素的下标来更新result数组。原创 2023-10-06 15:53:55 · 34 阅读 · 0 评论 -
739. 每日温度
加入T[4],T[4] == T[3] (当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况),此时依然要加入栈,不用计算距离,因为我们要求的是右面第一个大于本元素的位置,而不是大于等于!我们要保持一个递增单调栈(从栈头到栈底),所以将T[0]弹出,T[1]加入,此时result数组可以记录了,result[0] = 1,即T[0]右面第一个比T[0]大的元素是T[1]。加入T[1] = 74,因为T[1] > T[0](当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况)。原创 2023-10-06 15:11:49 · 32 阅读 · 0 评论 -
动态规划最强总结篇!
关于动规,还有 树形DP(打家劫舍系列里有一道),数位DP,区间DP ,概率型DP,博弈型DP,状态压缩dp等等等,这些在面试中出现的概率非常低。原创 2023-10-06 13:53:56 · 32 阅读 · 0 评论 -
516.最长回文子序列
其他情况dp[i][j]初始为0就行,这样递推公式:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);如果s[i]与s[j]不相同,说明s[i]和s[j]的同时加入并不能增加[i,j]区间回文子序列的长度,那么分别加入s[i]、s[j]看看哪一个可以组成最长的回文子序列。那么dp[i][j]一定是取最大的,即:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);加入s[j]的回文子序列长度为dp[i + 1][j]。原创 2023-10-06 13:49:21 · 27 阅读 · 0 评论 -
647.回文子串
如果这矩阵是从上到下,从左到右遍历,那么会用到没有计算过的dp[i + 1][j - 1],也就是根据不确定是不是回文的区间[i+1,j-1],来判断了[i,j]是不是回文,那结果一定是不对的。我们在判断字符串S是否是回文,那么如果我们知道 s[1],s[2],s[3] 这个子串是回文的,那么只需要比较 s[0]和s[4]这两个元素是否相同,如果相同的话,这个字符串s 就是回文串。注意因为dp[i][j]的定义,所以j一定是大于等于i的,那么在填充dp[i][j]的时候一定是只填充右上半部分。原创 2023-10-06 12:51:35 · 28 阅读 · 0 评论 -
动态规划之编辑距离总结篇
那最后当然是取最小值,所以当word1[i - 1] 与 word2[j - 1]不相同的时候,递推公式:dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});if (word1[i - 1] == word2[j - 1]) 那么说明不用任何编辑,dp[i][j] 就应该是 dp[i - 1][j - 1],即dp[i][j] = dp[i - 1][j - 1];原创 2023-10-06 11:57:48 · 76 阅读 · 0 评论 -
72. 编辑距离
72. 编辑距离原创 2023-10-06 11:45:37 · 27 阅读 · 0 评论 -
583. 两个字符串的删除操作
那最后当然是取最小值,所以当word1[i - 1] 与 word2[j - 1]不相同的时候,递推公式:dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});因为 dp[i][j - 1] + 1 = dp[i - 1][j - 1] + 2,所以递推公式可简化为:dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);dp[0][j]的话同理。原创 2023-10-06 10:57:22 · 37 阅读 · 0 评论 -
115.不同的子序列
和 dp[i][j] = dp[i - 1][j];当s[i - 1] 与 t[j - 1]不相等时,dp[i][j]只有一部分组成,不用s[i - 1]来匹配(就是模拟在s中删除这个元素),即:dp[i - 1][j]例如: s:bagg 和 t:bag ,s[3] 和 t[2]是相同的,但是字符串s也可以不用s[3]来匹配,即用s[0]s[1]s[2]组成的bag。所以当s[i - 1] 与 t[j - 1]相等时,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];原创 2023-10-05 21:40:10 · 28 阅读 · 0 评论 -
392.判断子序列
这道题目算是编辑距离的入门题目(毕竟这里只是涉及到减法),也是动态规划解决的经典题型。这一类题都是题目读上去感觉很复杂,模拟一下也发现很复杂,用动规分析完了也感觉很复杂,但是最终代码却很简短。在之前的题目讲解中,我们讲了1143.最长公共子序列,大家会发现 本题和 1143.最长公共子序列 的相似之处。原创 2023-10-05 21:03:07 · 151 阅读 · 0 评论 -
53. 最大子序和
而是dp[6]。在回顾一下dp[i]的定义:包括下标i之前的最大连续子序列和为dp[i]。那么我们要找最大的连续子序列,就应该找每一个i为终点的连续最大子序列。所以在递推公式的时候,可以直接选出最大的dp[i]。原创 2023-10-05 20:21:09 · 40 阅读 · 0 评论 -
1035.不相交的线
这个公共子序列指的是相对顺序不变(即数字4在字符串A中数字1的后面,那么数字4也应该在字符串B数字1的后面)现在,我们可以绘制一些连接两个数字 A[i] 和 B[j] 的直线,只要 A[i] == B[j],且我们绘制的直线不与任何其他连线(非水平线)相交。直线不能相交,这就是说明在字符串A中 找到一个与字符串B相同的子序列,且这个子序列不能改变相对顺序,只要相对顺序不改变,链接相同数字的直线就不会相交。我们在两条独立的水平线上按给定的顺序写下 A 和 B 中的整数。原创 2023-10-05 18:21:24 · 37 阅读 · 0 评论 -
1143.最长公共子序列
如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]即:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);原创 2023-10-05 17:42:39 · 34 阅读 · 0 评论 -
718. 最长重复子数组
如果定义 dp[i][j]为 以下标i为结尾的A,和以下标j 为结尾的B,那么 第一行和第一列毕竟要进行初始化,如果nums1[i] 与 nums2[0] 相同的话,对应的 dp[i][0]就要初始为1, 因为此时最长重复子数组为1。举个例子A[0]如果和B[0]相同的话,dp[1][1] = dp[0][0] + 1,只有dp[0][0]初始为0,正好符合递推公式逐步累加起来。即当A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;原创 2023-10-05 16:27:54 · 58 阅读 · 0 评论 -
674. 最长连续递增序列
本题也是动规里子序列问题的经典题目,但也可以用贪心来做,大家也会发现贪心好像更简单一点,而且空间复杂度仅是O(1)。在动规分析中,关键是要理解和动态规划:300.最长递增子序列的区别。要联动起来,才能理解递增子序列怎么求,递增连续子序列又要怎么求。概括来说:不连续递增子序列的跟前0-i 个状态有关,连续递增的子序列只跟前一个状态有关。原创 2023-10-05 15:14:20 · 49 阅读 · 0 评论 -
300.最长递增子序列
本题中,正确定义dp数组的含义十分重要。dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度为什么一定表示 “以nums[i]结尾的最长递增子序” ,因为我们在 做 递增比较的时候,如果比较 nums[j] 和 nums[i] 的大小,那么两个递增子序列一定分别以nums[j]为结尾 和 nums[i]为结尾, 要不然这个比较就没有意义了,不是尾部元素的比较那么 如何算递增呢。原创 2023-10-05 14:25:38 · 71 阅读 · 0 评论 -
714.买卖股票的最佳时机含手续费
所以:dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee);所以:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);dp[i][0] 表示第i天持有股票所省最多现金。dp[i][1] 表示第i天不持有股票所得最多现金。再来看看如果第i天不持有股票即dp[i][1]的情况, 依然可以由两个状态推出来。如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来。原创 2023-10-05 13:46:32 · 27 阅读 · 0 评论 -
309.最佳买卖股票时机含冷冻期
这次把冷冻期这道题目,讲的很透彻了,细分为四个状态,其状态转移也十分清晰,建议大家都按照四个状态来分析,如果只划分三个状态确实很容易给自己绕进去。原创 2023-10-05 13:19:25 · 34 阅读 · 0 评论 -
188.买卖股票的最佳时机IV
第二次买入依赖于第一次卖出的状态,其实相当于第0天第一次买入了,第一次卖出了,然后在买入一次(第二次买入),那么现在手头上没有现金,只要买入,现金就做相应的减少。选最大的,所以 dp[i][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][1]);所以dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])使用二维数组 dp[i][j] :第i天的状态为j,所剩下的最大现金是dp[i][j]原创 2023-10-05 12:08:42 · 81 阅读 · 0 评论 -
123.买卖股票的最佳时机III
例如 dp[i][1] ,并不是说 第i天一定买入股票,有可能 第 i-1天 就买入了,那么 dp[i][1] 延续买入股票的这个状态。一定是选最大的,所以 dp[i][1] = max(dp[i-1][0] - prices[i], dp[i - 1][1]);所以dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])那么dp[i][1]究竟选 dp[i-1][0] - prices[i],还是dp[i - 1][1]呢?你最多可以完成 两笔 交易。原创 2023-10-04 21:08:18 · 38 阅读 · 0 评论 -
122.买卖股票的最佳时机II
那么第i天持有股票即dp[i][0],如果是第i天买入股票,所得现金就是昨天不持有股票的所得现金 减去 今天的股票价格 即:dp[i - 1][1] - prices[i]。所以买入股票的时候,可能会有之前买卖的利润即:dp[i - 1][1],所以dp[i - 1][1] - prices[i]。中,因为股票全程只能买卖一次,所以如果买入股票,那么第i天持有股票即dp[i][0]一定就是 -prices[i]。唯一不同的地方,就是推导dp[i][0]的时候,第i天买入股票的情况。原创 2023-10-04 20:27:51 · 33 阅读 · 0 评论 -
121.买卖股票的最佳时机
由递推公式 dp[i][0] = max(dp[i - 1][0], -prices[i]);和 dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);同样dp[i][1]取最大的,dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);那么dp[i][0]应该选所得现金最大的,所以dp[i][0] = max(dp[i - 1][0], -prices[i]);原创 2023-10-02 21:43:06 · 41 阅读 · 0 评论 -
337.打家劫舍 III
这道题是树形DP的入门题目,通过这道题目大家应该也了解了,所谓树形DP就是在树上进行递归公式的推导。所以树形DP也没有那么神秘!只不过平时我们习惯了在一维数组或者二维数组上推导公式,一下子换成了树,就需要对树的遍历方式足够了解!贪心算法:我要监控二叉树!,这也是贪心算法在树上的应用。那我也可以把这个算法起一个名字,叫做树形贪心。“树形贪心”词汇从此诞生,来自「代码随想录」原创 2023-10-02 17:42:02 · 38 阅读 · 0 评论 -
213.打家劫舍II
成环之后还是难了一些的, 不少题解没有把“考虑房间”和“偷房间”说清楚。这就导致大家会有这样的困惑:情况三怎么就包含了情况一了呢?本文图中最后一间房不能偷啊,偷了一定不是最优结果。原创 2023-10-02 16:59:08 · 37 阅读 · 0 评论 -
198.打家劫舍
如果偷第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]);原创 2023-10-02 16:36:48 · 36 阅读 · 0 评论 -
背包问题:总结篇
背包问题是动态规划里的非常重要的一部分。关于这几种常见的背包,其关系如下:通过这个图,可以很清晰分清这几种常见背包之间的关系。确定dp数组(dp table)以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组这篇背包问题总结篇是对背包问题的高度概括,讲最关键的两部:递推公式和遍历顺序,结合力扣上的题目全都抽象出来了。原创 2023-10-02 16:07:44 · 57 阅读 · 0 评论 -
动态规划:关于多重背包,你该了解这些
多重背包在面试中基本不会出现,力扣上也没有对应的题目,大家对多重背包的掌握程度知道它是一种01背包,并能在01背包的基础上写出对应代码就可以了。至于背包九讲里面还有混合背包,二维费用背包,分组背包等等这些,大家感兴趣可以自己去学习学习,这里也不做介绍了,面试也不会考。参考资料代码随想录-动态规划:关于多重背包,你该了解这些!原创 2023-10-02 15:54:45 · 24 阅读 · 0 评论 -
139.单词拆分
稍加分析,便可知道本题是完全背包,是求能否组成背包,而且这里要求物品是要有顺序的。原创 2023-10-02 15:47:33 · 29 阅读 · 0 评论 -
279.完全平方数
,题目描述中可没说要从0开始,dp[0]=0完全是为了递推公式。从递归公式dp[j] = min(dp[j - i * i] + 1, dp[j]);此时我们要选择最小的dp[j],所以递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]);dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。dp[0]表示 和为0的完全平方数的最小数量,那么dp[0]一定是0。dp[j]:和为j的完全平方数的最少数量为dp[j]原创 2023-10-02 11:45:27 · 24 阅读 · 0 评论 -
322. 零钱兑换
细心的同学看网上的题解,可能看一篇是遍历背包的for循环放外面,看一篇又是遍历背包的for循环放里面,看多了都看晕了,到底两个for循环应该是什么先后关系。而本题是要求最少硬币数量,硬币是组合数还是排列数都无所谓!所以两个for循环先后顺序怎样都可以!原创 2023-10-02 11:16:22 · 22 阅读 · 0 评论 -
爬楼梯(背包角度解决)
本题看起来是一道简单题目,稍稍进阶一下其实就是一个完全背包!原创 2023-10-02 10:43:58 · 33 阅读 · 0 评论 -
377. 组合总和 Ⅳ
求装满背包有几种方法,递归公式都是一样的,没有什么差别,但关键在于遍历顺序!本题与动态规划:518.零钱兑换II就是一个鲜明的对比,一个是求排列,一个是求组合,遍历顺序完全不同。原创 2023-10-01 12:06:48 · 42 阅读 · 0 评论 -
518.零钱兑换II
本题的递推公式,其实我们在494. 目标和中就已经讲过了,而难点在于遍历顺序!在求装满背包有几种方案的时候,认清遍历顺序是非常关键的。如果求组合数就是外层for循环遍历物品,内层for遍历背包。如果求排列数就是外层for遍历背包,内层for循环遍历物品。原创 2023-10-01 11:46:11 · 34 阅读 · 0 评论 -
动态规划:完全背包理论基础
细心的同学可能发现,全文我说的都是对于纯完全背包问题,其for循环的先后循环是可以颠倒的!但如果题目稍稍有点变化,就会体现在遍历顺序上。如果问装满背包有几种方式的话?那么两个for循环的先后顺序就有很大区别了,而leetcode上的题目都是这种稍有变化的类型。这个区别,我将在后面讲解具体leetcode题目中给大家介绍,因为这块如果不结合具题目,单纯的介绍原理估计很多同学会越看越懵!原创 2023-10-01 10:42:07 · 34 阅读 · 0 评论 -
474.一和零
不少同学刷过这道题,可能没有总结这究竟是什么背包。此时我们讲解了0-1背包的多种应用,纯 0 - 1 背包是求 给定背包容量 装满背包 的最大价值是多少。416. 分割等和子集是求 给定背包容量,能不能装满这个背包。1049. 最后一块石头的重量 II是求 给定背包容量,尽可能装,最多能装多少。494. 目标和是求 给定背包容量,装满背包有多少种方法。本题是求 给定背包容量,装满背包最多有多少个物品。所以在代码随想录中所列举的题目,都是 0-1背包不同维度上的应用,大家可以细心体会!原创 2023-09-30 21:10:41 · 29 阅读 · 0 评论 -
494.目标和
此时 大家应该不禁想起,我们之前讲过的回溯算法:39. 组合总和是不是应该也可以用dp来做啊?是的,如果仅仅是求个数的话,就可以用dp,但回溯算法:39. 组合总和要求的是把所有组合列出来,还是要使用回溯法爆搜的。后面我们在讲解完全背包的时候,还会用到这个递推公式!原创 2023-09-29 17:42:44 · 34 阅读 · 0 评论