动态规划
无
47u1
好好学算法!
展开
-
买卖股票的最佳时机总结(动态规划)
这一类的变形题很多,更多的是我们要去思考这个题目的整体买卖路线,也就是持有和不持有的时候,需不需要再去细分,定义某些状态或者说一些很需要我们去定义的东西。这个其实就是K次,那么我们通过II来推算出,这个k次其实是有奇偶性规律的,然后我们推到到k就行。这个其实就是和最佳股票II一样,多了个小费,卖出的时候减去小费就行,没什么可说的。这唯一的不一样的就是把不持有的股票拆分成卖出股票,保持卖出股票和冰冻期的时候。这个其实我们就把这个拆分成两个状态就好,这个就可以直接通过状态转移去推到出来。原创 2024-10-20 16:44:16 · 62 阅读 · 0 评论 -
LeetCode714:买卖股票的最佳时机含手续费
这个题目其实就是卖卖股票II的变形,这个无非就是多了个小费,也就是在你卖出股票的时候,减去这个小费就好了。其他完全和买卖股票II一样。原创 2024-10-20 16:26:52 · 57 阅读 · 0 评论 -
LeetCode309:买卖股票的最佳时机含冷冻期
这个我们可以这么来看,就是我持有这个股票,那我前一天可以是持有,但我此时需要减去当前我买去这个股票的现金,第二个就是我们的股票是不是前一天也可能是卖出股票的状态,这个时候就是我们需要在保持卖出股票的状态减去现金,其次是不是我们也有可能在冷冻期的时候,也就是过完冷冻期刚好这一天,我给买下了这个股票,然后减去现金。这个就是我们的冷冻期,冷冻期的前一天肯定是卖出股票的状态的,因为卖出这个股票了,立马进入冷冻期了。//dp[i][1]保持卖出股票状态。//dp[i][2]卖出股票状态。//dp[i][3]冷冻期。原创 2024-10-20 13:28:27 · 109 阅读 · 0 评论 -
LeetCode188:买卖股票的最佳时机IV
思路没什么好说的,这个题目的关键就是怎么给你k值进行初始化数组而已,思路和买卖股票的最佳时机3一样。原创 2024-10-17 20:59:28 · 153 阅读 · 0 评论 -
LeetCode123:买卖股票的最佳时机III
这个就是要去取一个最大值了,那我要是当前持有的话,就要分两种情况,第一种是我之前就已经持有了,dp[i - 1][1], 第二个情况就是我之前就不持有,但我买了,所以就要不持有减去我买了股票的现金数,也就是 d p[i - 1][0] - prices[i]这个也是分两种情况,那我不持有,分两种情况,不持有的话那我之前就可能不持有,所以是dp[i - 1][2], 另一种情况是之前持有,所以我就要卖出去这个股票了,那我就要加上我当时卖出股票的钱。这个是我当前持有的,所以要买这个股票,要减去价钱。原创 2024-10-17 20:14:03 · 421 阅读 · 0 评论 -
LeetCode122:买卖股票的最佳时机II
这个题目实际上和LeetCode121一样的,区别就在于这个题目要求的是多次,121那个题目是一次,其实我们想想,多次,那么之前的一定是不持有股票且有利润的,而121那个题目是,刚开始钱为0的时候减去price[i],但是这个题目已经是获得利润了,所以是dp[i - 1][1] - prices[i];原创 2024-10-17 11:44:22 · 217 阅读 · 0 评论 -
LeetCode121:买卖股票的最佳时机
其次是递推公式,这个dp[i][0] = max(dp[i - 1][0], - prices[i]);,dp[i - 1][0]也是我i - 1的天数不持有股票的最大现金,要是我当i天持有了股票,那我就要减去price[i]这个递推公式dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);初始化:这个dp[0][0] = dp[0][0] - prices[0];也就是我当前持有股票,要减去price[0]原创 2024-10-17 11:15:11 · 272 阅读 · 0 评论 -
完全背包问题拓展(爬楼梯)
爬楼梯嘛,也就是说能够上楼梯的方法,三阶楼梯,我走1步再走2步,和我走2步再走1步,这个是两个不一样的方法,那么这个是不是又是一个排列问题了呢,我们要是这么来转换就好办了,肯定编写完全背包问题,先遍历背包,在遍历物品,然后就可以找到所有的方法能够爬到n阶楼梯了。题目思路,这个一看,哎,和70题有大不相同,我原本只需要1或者2步就可以爬了,这一下跳到m个,我该怎么去解开这个问题呢,其实呢,我们同学想一想,这个题目我们只要把。进阶版爬楼梯,在这里我就自己描述进阶版爬楼梯题目。原创 2024-10-15 20:49:59 · 121 阅读 · 0 评论 -
LeetCode377:组合总和IV
这个题目其实没什么好说的,代码思想和LeetCode518的零钱兑换思路基本一样,不同的是,那个题目先遍历物品在遍历背包,这个是组合数。而本题目是先遍历背包在遍历物品,这个是排列数,其中的一个代码if(i - nums[j] >= 0 && INT_MAX - dp[i - nums[j]] > dp[i])这个作用是为了防止整形溢出。原创 2024-10-15 20:43:22 · 296 阅读 · 0 评论 -
LeetCode213:打家劫舍II
那么有同学会想,要是数组是 1 6 9 6 100呢,这个也很好去解释,我们这个代码就是要去求(2)(3)这两个的最大值,也就是当后面是100的话,那么是不是去掉首元素,保留末尾元素是最大值呢,毕竟代码之前写过一个这个return max(result1, result2);这个题目的关键思想就在于,你是怎么把环拆开成线性数组去求解的,这个题目分为三种情况,(1)不考虑首尾元素(2)不考虑首元素(3)不考虑尾元素。那么是不是(2)(3)都出现了6 9 6,所以(2)(3)是把(1)包含着了。原创 2024-10-15 20:14:53 · 191 阅读 · 0 评论 -
LeetCode198:打家劫舍
这个是我们只看最后一个,也就是最后一个物品偷还是不偷,如果偷的话,那就是dp[i - 2] + nums[i], 不偷的话,那就是dp[i - 1]之前的房间,这个不一定是倒数第二个,也可能是倒数第三个,第四个.......初始化,dp[0]毫无以为就是nums[0],dp[1]也就是我要选前两个之家最大的数。原创 2024-10-15 12:35:42 · 288 阅读 · 0 评论 -
LeetCode279:完全平方数
这个没什么好说的,和零钱兑换那个差不多,唯一注意的就是for循环里面的是i * i <= n,因为平方数,所以就是i的平方了。原创 2024-10-14 09:30:58 · 222 阅读 · 0 评论 -
LeetCode322:零钱兑换
INT_MAX),这个是为什么呢,因为我们需要找到当前dp数组是被初始化的,然后我们才能进行下一步赋值,如果这个数组没有被初始化了,也就是不满足这个背包问题了。原创 2024-10-13 17:31:03 · 244 阅读 · 0 评论 -
LeetCode518:零钱兑换
题目讲解:首先我们要知道这个题目要求的是有几种方法可以凑成这个amount,也就是我把amount当成一个背包容量,既然说钞票无限使用,我们肯定想到的是用完全背包。这个求出来的是凑出这个amount的排列数,因为是把背包定下来的,背包里面放入物品1,2,3.....,所以来说背包里面的物品是没有先后顺序的,所组成的数就是{1,2},{2,1},这两个都能讲的通。,为什么这么说的,因为先遍历物品,肯定是先遍历1,然后遍历2,所以背包里面的组合就是有顺序的,{1,2}这个求出来的是凑出这个amount的。原创 2024-10-10 12:01:39 · 312 阅读 · 0 评论 -
信奥一本通1268:【例9.12】完全背包问题
题目解释:这个要求也就是正如题目所说的,完全背包问题,完全背包问题和01背包问题不同的区别就是,01背包问题的每个物品只能用一次,而完全背包的物品可以使用无数次,01背包优化后的1维dp的for循环是不能够调换顺序的,并且第二层for循环背包还得需要从后往前遍历才能保证每一个物品只用了一次,而完全背包则是从前往后开始,这样就能保证每一个物品可以使用多次或者无数次,而且完全背包的两个for循环可以调换。代码:这里给的是先遍历的物品,后遍历的背包容量。原创 2024-10-10 08:50:29 · 227 阅读 · 0 评论 -
LeetCode474:一和零
这里要讲一下递推公式是怎么来的,其实这个也就是相当于三维数组了(没优化先),01背包优化之后遍历的时候都需要两层for循环了,所以这个多维度的背包问题,肯定就是需要三重for循环。这个代码其实也很好的理解为是多维度的01背包问题,也就是说,我们有两个背包容量,去选择价值最大的物品,首先我们需要先遍历这个字符串的数组的每一个字符,先把字符的0和1分别统计下来,然后去统计好oneNum和zeroNum的数值,再去用01背包的递推公式去解开这个问题。原创 2024-10-08 21:13:24 · 272 阅读 · 0 评论 -
LeetCode494:目标和
这个题目也可以这么理解,怎么把加法和减法做一个排列组合,主要是这个dp[j] = dp[j - nums[i]];这个是怎么推导出来的。如果我们选了物品1,那么就有dp[4]种方法凑成dp[5],选择物品2的话,有dp[3]凑成dp[5],以此类推,那么dp[5] = dp[4] + dp[3] + dp[2] + dp[1] + dp[0];这里的初始化还是有很大的学问的,这里需要把dp[0] = 1;原创 2024-10-08 13:37:23 · 586 阅读 · 0 评论 -
LeetCode1049:最后一块石头的重量
这个题目要知道最后返回的值是有些考究的,返回是sum - 2*dp[target];,为什么呢,因为dp[target]是向下取整并且dp[target]是最小堆的石头,所以另一堆石头的重量就是sum-dp[target],两个石头堆相减,也就是最后的结果sum - 2*dp[target]这个题目的关键思想就是需要把这些石头能够以相差最小的值分成两堆,也就是说,分成两堆的石头每一堆的重量加起来再相减的和最小即可。这个题目没得说,也就是把所有的石头加起来,sum除以2,得到的值,作为背包的容量大小即可。原创 2024-10-07 20:26:39 · 656 阅读 · 0 评论 -
LeetCode416:分割等和子集
代码讲解:这个题目首先我们要明白一件事情,就是要把这个分成一个相等的子集,那么其实我们就可以看似为一个01背包问题,怎么去转化为这个01背包,就是我们先把所有的子集加起来除以2,就是背包大小,看看里面的子集能不能刚刚好填满这个背包,要是能的话,返回true,否则返回false,这个里面要注意的是,if(sum % 2 == 1)return false;这个原因是因为要是奇数的话,有小数点,你放进去的东西不能够是半个吧,因为题目都给你的全是整形数据。原创 2024-09-23 17:29:55 · 348 阅读 · 0 评论 -
1267:【例9.11】01背包问题(从二维优化一维dp问题)
至于说一维dp问题,里面有很许多要注意的细节,与二维dp做比较,有很多问题,以下我一一列举下来,我也一一给出答案。这个代码能够优化到一维的数组,因为你可以这样理解,就是二维数组的每一行,全部把他放到一行里面去,也就是下面这个转换。问:为什么二维背包的遍历顺序背包或者物品重量都可以调换,而优化后一维dp的遍历顺序一定要先是物品然后才是背包?答案:因为二维背包先遍历物品或者先遍历背包都是可以的,因为后面的结果都是基于行和列来算出的结果。原创 2024-09-23 13:25:04 · 252 阅读 · 0 评论 -
LeetCode118:杨辉三角
代码讲解:这个题目没有任何难度,就是推到公式,当第三行的时候就需要上面的两个相加,递推公式也就是dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j], 重点,二维vector开拓三角形数组需要 dp[i].resize(i + 1);也就是第1行开1个单位数组,第2行开2个单位的数组,以此类推。最后的形状是个上三角形。感悟:最搞笑的是我就坏到怎么处理这个上三角的问题,真的是,唉,吃一只长一智。原创 2024-09-20 19:37:39 · 307 阅读 · 0 评论 -
LeetCode746:使用花费最小爬楼梯
这个问题也就是我们需要最小的花费爬楼梯,首先先想到动态规划里面的解题步骤,我们先定义dp[i]的含义,dp[i]也就是我们爬到顶楼花费最小,这个时候数组的最后一个索引不是顶楼,而是N+1,一次只能爬一次或者两次。然后初始化这个dp,其实我们想想,最主要影响的dp是cost这个花费,而不是dp[i]。例如dp[i - 1]这个意思也就是我最后一步加上cost[i - 1]这个值,最后花费最少。注意判断cost数组为0和1的情况。原创 2024-09-19 12:58:40 · 350 阅读 · 0 评论 -
1267:【例9.11】01背包问题(信奥一本通,二维dp)
代码讲解:只讲核心。先确定dp[i][j]的含义,正如我解释所说的,dp[i][j]表示着在有限的容量内使背包里面物品价值总和最大。然后就根据这个含义定义好dp[i][j]的状态转移方程,dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + c[i]),为什么是max而不是min,也很好理解,也就是我们需要求最大的价值,所以就要用max。今天刚看完卡尔大哥讲解的01背包,今天手敲了一遍,还是很多问题,只能说自己还是刷题太少或者说是没理解到位。原创 2024-09-20 19:29:51 · 246 阅读 · 0 评论 -
动态规划的解题步骤,给自己看的
例子:斐波那契数列//最后一步:前面的数据已经算好,最后一步数据只需要拿到它的前两个数据即可//dp数组的含义:第i个数的斐波那契是dp[i]//状态转移方程:dp[i] = dp[i - 1] + dp[i – 2]//dp数组的初始化;dp[0] = 0;dp[1] = 1;实例代入:dp[5] = dp[4] + dp[3]过程:dp[5] = 5;dp[4] = 3;dp[3] = 2;dp[2] = 1;return n;dp[0] = 0;dp[1] = 1;原创 2024-09-19 13:04:11 · 155 阅读 · 0 评论 -
LeetCode63:不同路径II
(2)if里面的判断语句,我居然写成了dp[i][j] == 1,我感觉我的脑子真是有坑,不知道怎么想的,实际上现在想想,并不是dp[i][j] == 1,毕竟我们要求的是dp[i][j],所以肯定是得需要原先的数obs来判断障碍物。这个题目其实也就是多加了一个条件,多了障碍物,不能走。这个时候要对初始化进行一定的判断。(1)好长时间都没用vector这个二维数组了,我连遍历都忘了怎么遍历了。原创 2024-09-19 12:48:11 · 285 阅读 · 0 评论 -
LeetCode62:不同路径
代码如下class Solution {public: int uniquePaths(int m, int n) { vector<vector<int> > dp(m, vector<int>(n, 0)); for(int i = 0; i < m; i++) { dp[i][0] = 1; } for(int j = 0; j < n原创 2024-09-19 12:04:47 · 301 阅读 · 0 评论 -
LeetCode509:斐波那契数列
实际上我代码里面都是我要讲的东西了,同学们很多时候编写斐波那契,就喜欢按照正常的编写或者递归,实际上这两种都可以,但是有些时候题目要求限制时间的话,那就只能以空间换时间,动态规划的本质就是,把之前的求的数据存到dp数组中,后面可以用dp数组转移,然后占据较大空间来减少时间复杂度。原创 2024-09-15 23:14:28 · 319 阅读 · 0 评论 -
LeetCode70:爬楼梯
看着程序员卡尔的动态规划五部曲也就是五步走,然后确定dp状态转移方程,最后算出来n的时候有多少种方法走上台阶。也就是斐波那契数列,区别就在n = 0时,这个题目没有n = 0,也就是没有0阶楼梯这一说法。这个题目也就是最简单的动态规划,题目很难理解,实际上当你递推几个之后就好办了很多。n = 1 有1种方法。n = 2 有2种方法。n = 3 有3种方法。n = 4 有5种方法。n = 5 有8种方法。原创 2024-09-15 23:04:40 · 390 阅读 · 0 评论