![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
动态规划
c葱c
这个作者很懒,什么都没留下…
展开
-
leetcode 516.最长回文子序列
需要考虑 i j 相等的情况。还有遍历顺序是逆序的。原创 2023-05-10 10:06:06 · 48 阅读 · 0 评论 -
leetcode 647. 回文子串
递推公式中,有 dp[i + 1][j - 1] ,这个是在 dp [ i ][ j ] 的左下方,所以需要从下往上,从左往右遍历,以保证每次推导的都是有依据的值,而不是一开始被初始化的值。全部初始化成 fasle,因为一开始还没开始匹配。值:i 到 j 的字符串中回文字符串的个。下标:i 到 j 的字符串中。1. dp数组的含义。原创 2023-05-10 09:26:35 · 37 阅读 · 0 评论 -
leetcode 72. 编辑距离
dp[i][j] = min(min(dp[i - 1][j] + 1, dp[i][j - 1] + 1 表示的是删除元素,因为增加元素和删除元素是一样的,具体的原因后面理解深刻了再说,现在还讲不太清楚。dp[i - 1][j - 1] + 1 这个表示的是替换元素,在之前的基础上替换。原创 2023-05-09 15:48:32 · 41 阅读 · 0 评论 -
leetcode 115. 不同的子序列
这里并没有进行 + 1 的操作,因为字符相等,但所包含的个数并不会 + 1。着重理解dp数组的含义,表示的是 s 含有 t 的个数,这道题还没有理解,等之后有空再回来看。原创 2023-05-09 11:31:45 · 62 阅读 · 0 评论 -
leetcode 583. 两个字符串的删除操作
1. 用最长公共子序列处理,就是两个字符串的总和,减去两倍的最长公共子序列,得到的差就是最小删除字符的操作。原创 2023-05-09 11:14:32 · 79 阅读 · 0 评论 -
leetcode 392. 判断子序列
值:以 i - 1 和 j - 1 为结尾的字符串的相同子序列长度。我之前的错误想法是:用两个循环嵌套。,其实是两个字符串的指针一致移动。下标:以 i - 1 和 j - 1 为结尾的字符串。和之前一样初始化成 0。1. dp数组的定义。原创 2023-05-08 11:50:56 · 36 阅读 · 0 评论 -
leetcode 392. 判断子序列
值:以 i - 1 和 j - 1 为结尾的字符串的相同子序列长度。我之前的错误想法是:用两个循环嵌套。,其实是两个字符串的指针一致移动。下标:以 i - 1 和 j - 1 为结尾的字符串。和之前一样初始化成 0。1. dp数组的定义。原创 2023-05-08 11:11:26 · 36 阅读 · 0 评论 -
leetcode 53. 最大子数组和
最后的结果是在 dp 数组中,寻找最大的一个数,而不是最后一个数,因为最大子数组和 不一定包括最后一个 元素。dp[i - 1] + nums[i] : 表示由前面一个推到 i。nums[i] : 从现在 i 开始重新计数。值:包括 i 的子数组的最大和。下标:包括 i 的子数组。1. dp数组的定义。原创 2023-05-06 11:14:18 · 62 阅读 · 0 评论 -
leetcode 1035. 不相交的线
只是换了一个壳子而已。原创 2023-05-06 10:59:18 · 68 阅读 · 0 评论 -
leetcode 1143. 最长公共子序列
例如:abcd abe,此时的 c 和 e 不相等,所以就向前比较,ab 与 abe。例如:abcd abe,此时的 c 和 e 不相等,所以就向前比较,abc 与 ab。3. 初始化,因为是从 dp数组的定义是从 i - 1 和 j - 1 进行比较的,所以可以默认初始化。值:以 i - 1 和 j - 1 为结尾的最长公共子序列的长度。下标: 以 i - 1 和 j - 1 为结尾的子序列。i - 1 之后,再与当前的 j 比较。j - 1 之后,再与当前的 i 比较。1. dp 数组的定义。原创 2023-05-06 10:22:30 · 292 阅读 · 0 评论 -
leetcode 718. 最长重复子数组
i : nums1 以 i - 1 为结尾。j : nums2 以 j - 1 为结尾。值: 分别以上述为结尾的最大重复子数组的长度。使用二维数组的不同维度分别表示 num1 和 num2。也就是由前面一个推到后面一个。1. dp数组的含义。原创 2023-05-05 15:04:47 · 66 阅读 · 0 评论 -
leetcode 674. 最长连续递增序列
1. 第一个想法是双指针。原创 2023-05-05 14:37:37 · 59 阅读 · 0 评论 -
leetcode 300.最长递增子序列
也就是说,如果 num[ i ] > nums [ j ],就说明子序列的个数要 + 1, 所以 dp[j] + 1。在所有的比较中,dp [ i ] 取最大值,因为 i 在 j 循环的时候, i 是固定的 ,所以就会出现当,j 不。值: 表示包括 i 之前的最大的递增子序列。断移动的时候, dp [ i ] 会出现改变,所以要求的是最大值。下标:第 i 个数字。因为是根据前一个推导出后一个的。一开始都初始化成 1。原创 2023-05-05 12:09:54 · 165 阅读 · 0 评论 -
leetcode 714.买卖股票的最佳时机含手续费
卖出的时候减去了手续费。原创 2023-05-04 10:32:54 · 68 阅读 · 0 评论 -
leetcode 309.最佳买卖股票时机含冷冻期
这里将 “ 当天卖出” 单独拿出来,是因为本题存在冷冻期,而冷冻期的前一天是当天卖出的状态。如果不单独拿出来的话,那么冷冻期的前一天就是 不持有股票的状态,不持有股票有两种状态,这里就无法做出准确的区分了。原创 2023-05-04 09:53:56 · 61 阅读 · 0 评论 -
leetcode 188.买卖股票的最佳时机IV
其实个人觉得和 买卖股票的最佳时机III,是一样的,就是多用下标来表示状态即可。这里两个关于 j 的循环起始位置不一样,这和循环中的内容有关。找出规律就可以用循环来解决啦~j 的循环 是两个两个跳的。原创 2023-05-03 14:32:08 · 70 阅读 · 0 评论 -
leetcode 123.买卖股票的最佳时机III
因为最后一定是不持有股票的利润最大,而第二次不持有会包含第一次不持有的状态(也就是第一次不持有后,在同一天买入并卖出,这时候第二次不持有和第一次不持有的利润是一样的,2. 因为遍历数组是有先后顺序的,在递推公式中也有买卖的先后顺序,所以不用管可能会连续买入两次的情况,因为递推公式里面的推导不会导致这种情况的发生。一开始被 至多 买卖两次给唬住,想的是用一个变量表示买卖的次数;i 表示天数 , 1 2 3 4表示对应的状态。有四个下标表示两次的状态 (持有 / 不持有。如果还是不理解就取最大值。原创 2023-05-03 14:05:02 · 70 阅读 · 0 评论 -
leetcode 122.买卖股票的最佳时机II (动规
因为不止可以买入一次,所以是在之前未持有的股票的基础上,所拥有的利润买的。第 i 天买的:dp[i - 1][1] - prices[i]第 i 天之前买的:dp[i - 1][0]跟 买卖股票的最佳时机I 的区别在于。原创 2023-05-02 16:38:45 · 50 阅读 · 0 评论 -
leetcode 121. 买卖股票的最佳时机 (贪心 + 动规 + 双指针
(这里没有使用买入、卖出作为含义是因为:单纯的买入,卖出,无法表示出更确切的状态。现在觉得做动规的关键点就是找出,当前的状态是否与之前的状态有关,也就是说:当前一般会有两种状态,具体哪一种为最优,需要依靠之前的状态及逆行推导。dp [ i ] [ 1 ] 表示第 i 天不持有股票, 值为:所获得的利润。第 i 天卖出: dp [ i - 1][ 0 ] + price[ i ]dp [ i ] [ 0 ] 表示第 i 天持有股票,值为:所获得的利润。第 i 天之前就买入了:dp[ i - 1][ 0 ]原创 2023-05-02 16:21:51 · 1002 阅读 · 0 评论 -
leetcode 337.打家劫舍III
不偷:max(left[0], left[1]) + max(right[0], right[1])、在二叉树中,可以使用后序遍历,先遍历两个子节点,再到根结点,根结点根据子节点是否偷,再决定当前结点。表示根结点不偷取,两个子节点选取金币数最大的状态( 0 或 1 )写一个递归函数,返回值为 一维数组,对应的就是当前结点偷和不偷,所对应的金币数。所以这里的每个结点有两个状态 偷(1 还是 不偷(0,对应一个一维数组。偷:root->val + left[0] + right[0]原创 2023-05-01 20:07:46 · 98 阅读 · 0 评论 -
leetcode 打家劫舍II
做出来了,但是没想到封装成一个函数,造成了代码的冗余。原创 2023-05-01 17:10:05 · 64 阅读 · 0 评论 -
leetcode 198.打家劫舍
dp[i - 2] + nums[i] : 当前房子偷,最大金币数来源于前 i - 2 个房子,和当前的房子,前一个房子不能被偷,因为不能偷相邻的。如上所述 dp[i] = max(dp[i - 1] , dp[i - 2] + nums[i]);讨论大小为 1 的原因是:之后的都是根据1 来推的,如果数组大小只有1 的话,就没有往下继续推的必要了。dp[i - 1] : 当前房子不偷,所以最大的金币数都来源于前 i - 1个房子,包括第 i - 1 个。值:这些房子所得到的最大金币数。原创 2023-05-01 16:35:17 · 890 阅读 · 0 评论 -
leetcode 139.单词拆分
将字符串当作是背包,字符串数组里面的元素当作物品,本题求的是,物品能否将背包装满。为了后面递推公式的计算这里初始化 dp [ 0 ] = true。因为这里不同的顺序意味着不同的字符串,所以对顺序是由要求的。{ap} {pa} 不能看作是同一个字符串。先 背包 后 物品 ,求的是排列数。1. dp 数组的含义。原创 2023-04-29 16:38:35 · 70 阅读 · 0 评论 -
279.完全平方数
本题和零钱兑换 1 十分类似 ,只是物品变了,物品变成了 i * i。原创 2023-04-28 18:00:11 · 57 阅读 · 0 评论 -
322. 零钱兑换 ( 完全背包
这里 + 1 表示放入了 i ,所以个数 + 1。和之前加价值不一样,因为dp数组的含义变了。凑到 0 ,不需要硬币,所以数量也为 0 ( 这里和之前也不一样。因为求的的硬币的个数,而不是方案的数量,所以嵌套的前后也不会影响。放入 i :dp[j - coins[i]] + 1。由于是完全背包, 所以都是顺序遍历。不放入 i :dp[j]下标:需要凑到的钱总和。值:最小需要多少个硬币。1. dp数组的含义。原创 2023-04-28 17:41:28 · 94 阅读 · 0 评论 -
leetcode 70. 爬楼梯 (完全背包
之所以是完全背包是因为,之前上了一阶 后面还能继续上一阶。物品 是 一次能够上的台阶数 1 2 3......背包容量是一共要上的台阶数。这道题也可以用背包来解决。演变为完全背包的问题。原创 2023-04-28 17:31:08 · 66 阅读 · 0 评论 -
leetcode 377. 组合总和 Ⅳ (完全背包
先确定背包的大小,再遍历物品,这样就会出现 { 2 , 1 } { 2 , 1 } 的情况,因为物品是在内循环中,很有可能会出现先加入了大的,后加入小的 的情况。和零钱兑换的那道题基本一模一样,不同点在于最后 for循环嵌套先后。先背包,后物品(排列。这里需要防溢出 ( C++原创 2023-04-27 19:33:34 · 76 阅读 · 0 评论 -
leetcode 518. 零钱兑换 II (完全背包
取 i : dp [ j - conis[ i ] ] 也就是凑到剩余 j - conis[ i ],需要的方案。dp [ 0 ] = 1,如果初始化成 0 , 那之后都是 0 , 无法递推累加了。且背包需要正序遍历,因为物品是可以重复取得,且不受上一层得影响。本题是求:一共有多少种方法可以将背包装满 ( 与目标和 那道递推公式类似。不取 i : dp [ j ]值:凑到当前和有多少种方法。1. dp [ j ] 数组的含义。原创 2023-04-27 17:49:58 · 737 阅读 · 0 评论 -
leetcode 474.一和零 (01背包 二维
背包倒序:因为也是要使用到之前的 dp[i - zeroNums][j - oneNums] 的状态。dp[0][0] = 0 当前没有放入任何东西,其它的跟之前题一样,初始化成最小的非负整数。下标:i 表示 0 的数量,j 表示 1 的数量。这里涉及到三个变量: 0 的个数,1 的个数,背包中的数量。这个 + 1 就是表示背包中多了一个字符串。值:表示当前背包的放入字符串的最大数量。不放入当前的字符串:dp[i][j]1. dp[ i ] [ j ] 的含义。所以不能压缩成一维的 01背包。原创 2023-04-27 15:18:24 · 398 阅读 · 0 评论 -
leetcode 494. 目标和 (01 背包
意思是,如果选择了 i , 则 剩下要组成和为j - nums [ i ] 的方案数就等于dp[ j - nums [ i ] ]例如:集合 [ 0 ] target = 0 , 此时就只有一种方法。需要求出和为 (target + sum(nums)) / 2 的方案有多少个。就当作是 和 为0 的方式 只有一种。分成两个集合 (注意这里计算的时候是不带上符号的,只是单纯的数字。选i :dp [ j - nums[ i ] ]值: 和为 j 的方案有多少个。和之前一样,物品正序,背包倒叙。原创 2023-04-27 11:34:27 · 760 阅读 · 0 评论 -
leetcode 1049. 最后一块石头的重量 II (01背包
然后求这 两堆之差 sum - dp [target] - dp [target]首先就将这一堆石头尽量分成两堆一样重量, 重量: target = sum / 2。两堆 dp [target] sum - dp [target]这里的规则是求出碰撞后最小的石头是多少。与 01 背包 分割子集的题目类似。求出这一堆石头总的重量 sum。原创 2023-04-27 09:37:54 · 45 阅读 · 0 评论 -
416. 分割等和子集 (01背包
这样做的目的是,如果找到了 sum/2 ,那么剩下的一部分,必然是 sum / 2,也就是元素相等。都初始化成最小的非负整数,也就是0。如果太大就会把其它的覆盖掉。所以我们希望找的是 dp [target] = target。和 01 一维的一样。不过这里需要注意的是 价值 == 重量。把这个数组所有元素的和 / 2 ,得到一个target。也就是刚好装满,这里的元素的 价值等于重量。物品在外层,背包在内层,且一定要倒序。值:表示背包当前容纳的价值。原创 2023-04-26 21:08:08 · 65 阅读 · 0 评论 -
01 背包 (一维)
dp [ j - weight[i] ] + value[ i ] 是放入 物品 i ,dp [ j - weight[i] ] 是没放入 物品 i 之前的最大价值 ,现在放入物品 i , 就是放入物品 i 后的最大价值。dp [ i ] [ j ] dp [ i - 1] [ j ] 正是因为有 i 这个变量作为维度,所以就保留了上一层的状态。因为dp数组中的 i j 需要的是左上 和 上方 的值,与遍历顺序无关。我们可以利用到上一层的信息,根据上一层的信息,得到本层的信息。原创 2023-04-26 16:55:26 · 364 阅读 · 0 评论 -
01 背包 (二维 )
放物品 i : dp[ i ] [ j ] = dp[ i - 1 ] [ j - weight[ i ] ] + value[ i ] )不放物品 i :dp[ i ] [ j ] = dp[ i - 1 ] [ j ] (也就是,和上一层的值是一样的。有一个背包可以放下 n kg,有一些物品,价值和重量一一对应,问题是,需要怎样才能使背包中的价值最大?因为当前的值,是依靠左上 或者 上方的 值来的,和遍历顺序没有关系。1.dp[ i ] [ j ] 数组的含义。原创 2023-04-26 16:11:43 · 730 阅读 · 0 评论 -
leetcode 96.不同的二叉搜索树
解释不太清,大概意思上就是,可以由n = 1 和 n = 2 推导出 n = 3 的情况。i - j : 表示的是 以 j 为根结点的 右子树 一共有多少种。j - 1 : 表示的是 以 j 为根结点的 左子树 一共有多少种。dp [ 0 ] = 1 把 空树 也当作时一种二叉搜索树。值:表示整数 0 - i 可以组成多少种二叉树。下标:表示 整数 i。4. 遍历顺序,从小到大。1. dp数组的含义。原创 2023-04-24 11:46:42 · 81 阅读 · 0 评论 -
leetcode 343. 整数拆分
注意在写代码的时候,求最大值,需要将dp [ i ] 包括进去,因为它会记录下每次的最大值,需要更新的话,需要与它比较。2. dp [ i - j] * dp [ j ] 拆分成 三个 及其三个以上 拆分 j 和 i - j。dp [ 0 ] dp[ 1 ] 都是不能被拆分的 ,所以初始化没有意义。1. j *( i - j ) 拆分成两个数,j 是其中一个因数。第一层循环是 需要被拆分的整数。值:表示 被拆分之后 的乘积。下标:表示需要被拆分的整数。第二层循环时 寻找质因数。原创 2023-04-24 10:57:26 · 480 阅读 · 0 评论 -
leetcode 63. 不同路径 II
只有当 i,j 不是 障碍,才可以从其它的地方走到 i,j。遇到 1 就退出,不进行初始化了。由给出的参数得到dp所需要的 m n。原创 2023-04-22 13:14:56 · 54 阅读 · 0 评论 -
leetcode 62.不同路径
初始化最左边和最上面的元素,因为 要向右 / 下 走,是由左和上推出来的。由于只能向右走,或者向下走,所以走到 i,j的方法有两种。值: 走到i ,j 的方法有多少种。下标: 表示i , j 的方式。1. dp数组 下标及其 值 的含义。原创 2023-04-22 12:11:36 · 68 阅读 · 0 评论 -
leetcode 746. 使用最小花费爬楼梯
cost[ i ] 是第 i 阶 需要向上爬的费用,可以选择爬 一阶 或者 两阶。走一步 花费 cost[ i - 1]走两步花费 cost[ i - 2]1. 走一步 dp[i - 1]2. 走两步 dp[i - 2]原创 2023-04-21 15:30:41 · 55 阅读 · 0 评论 -
leetcode 70. 爬楼梯
没想到思路和 斐波那契数列 这么像。2. 遍历的时候,下标从 3 开始。原因: 走到 第 n 阶可以。1. 初始化下标从 1 开始。原创 2023-04-21 11:52:24 · 29 阅读 · 0 评论