动态规划
文章平均质量分 62
动态规划
hlc@
这个作者很懒,什么都没留下…
展开
-
【状态机DP】力扣1186. 删除一次得到子数组最大和
呢,因为我们在之前dp[i][0]中如果前面dp[i-1][0]为负数,则以arr[i]重新开始计算,但是由于现在的dp[i][1]要求必须删除一个元素,那么不可能从arr[i]开始算起,但是没有删除任何元素。我们定义一个动态规划数组dp,dp[i][0]代表以arr[i]结尾的子数组,并且没有删除过元素,dp[i][1]代表以arr[i]结尾的子数组,并且删除过元素。解释:我们可以选出 [1, -2, 0, 3],然后删掉 -2,这样得到 [1, 0, 3],和最大。所以我们有状态转移方程。原创 2024-10-27 12:20:08 · 379 阅读 · 0 评论 -
【状态机DP】【记忆化搜索&&1:1翻译递归&&空间优化】力扣2771. 构造最长非递减子数组
然后我们这时候进行判断,看我们现在nums[j][i]与nums1[i-1]和nums2[i-1]进行比较,如果大于等于他们,则说明我们这时候的最大非递减子序列长度就是要么dfs(i-1, 0)+1,要么就是dfs(i-1, 1)+1,取两者最大值即可。,f[i][j]都是由上一轮i-1转换而来,由于我们在使用一位数组的时候,会存在覆盖,使f[j]变成这一轮计算过的值而不是上一轮,所以我们在每一轮开始的时候,通过两个变量t0和t1来记录上一轮的f[0]和f[1]供着一轮的状态转移使用。原创 2024-10-23 16:54:38 · 827 阅读 · 0 评论 -
【状态机DP】力扣1395. 统计作战单位数
作战单位需满足: rating[i] < rating[j] < rating[k] 或者 rating[i] > rating[j] > rating[k] ,其中 0 <= i < j < k < n。从队伍中选出下标分别为 i、j、k 的 3 名士兵,他们的评分分别为 rating[i]、rating[j]、rating[k]rating[i] < rating[j] < rating[k],则有iless * kmore种组合。n 名士兵站成一排。输入:rating = [2,5,3,4,1]原创 2024-10-23 15:45:32 · 224 阅读 · 0 评论 -
【状态机DP】【hard】力扣1363. 形成三的最大倍数
还有一个重要的问题是,我们在最后对ans进行reverse操作,那么我们能不能在i从0-9循环,进行从9-0倒序循环,然后不使用reverse操作呢?答案是不可以,因为涉及到我们的remove_mod操作,如果使用倒序,那么会优先删除最大的符合余数条件的字符,而我们要删除的是最小的符合条件的字符,这样才能让ans达到最大。给你一个整数数组 digits,你可以通过按 任意顺序 连接其中某些数字来形成 3 的倍数,请你返回所能得到的最大的 3 的倍数。输入:digits = [0,0,0,0,0,0]原创 2024-10-23 00:38:27 · 481 阅读 · 0 评论 -
【状态机DP】力扣1262. 可被三整除的最大和
可能受到前面计算的影响,因为我们转移的dp是之前的状态,而如果直接使用dp,那么有的dp会被更新成目前状态,导致后续计算出错。没有选任何元素时,和为0是合法的解,并且0是可以被3整除的,所以我们在初始化时,令dp[0] = 0。解释:选出数字 1, 3, 4 以及 4,它们的和是 12(可被 3 整除的最大和)。解释:选出数字 3, 6, 1 和 8,它们的和是 18(可被 3 整除的最大和)。输入:nums = [3,6,5,1,8]输入:nums = [1,2,3,4,4]输入:nums = [4]原创 2024-10-21 22:25:41 · 345 阅读 · 0 评论 -
【状态机DP】力扣2786. 访问数组中的位置使分数最大
在访问位置i的时候,假设i是奇数,则最大的dp[1]有可能是从上一个最大dp[1]加上当前nums[i]转移而来,或者是从上一个最大dp[0]加上nums[i]减去x转移而来,由于nums[i]在题目中大于0,则cur无论如何都会比之前的dp[1]要大。对于这道题目,我们可以定义一个容量为2的dp数组来说明他的奇偶性,并储存最后移动的元素为偶数时得分的最大值和最后移动的元素为奇数时得分的最大值。输入:nums = [2,3,6,1,9,2], x = 5。注意 ,你一开始的分数为 nums[0]。原创 2024-10-21 18:02:47 · 549 阅读 · 0 评论 -
【状态机DP】1567. 乘积为正数的最长子数组长度
当nums[i]<0的时候,a[i]从b[i-1]+1转化而来,但是如果b[i-1]为0,也就是说以nums[i]结尾的最长负数子数组的长度为0,则说明a[i]不能通过之前的负数乘积来乘以当前负数的nums[i]来得到一个正数,那么由于当前nums[i]也是负数,所以当b[i-1]为0的时候,a[i]也为0。当nums[i]>0的时候,a[i]由a[i-1]+1转换而来,b[i]由b[i-1]转换而来,如果b[i-1]为0,那么b[i]也为0。输入:nums = [-1,-2,-3,0,1]原创 2024-10-20 17:21:14 · 348 阅读 · 0 评论 -
【状态机DP】【贪心】力扣376. 摆动序列
表示nums[i]可以接在down[i-1]的最长下降摆动子序列后面的情况,那怎么能说明down[i-1]中的最长下降摆动子序列的最后一个元素不大于nums[i-1]呢,实际上我们可以采用反证的方法,如果down[i-1]中最长下降摆动子序列的最后一个元素大于nums[i-1]的话,那么nums[i-1]则会成为down[i-1]的最后一个元素。其中一个是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8)。,其中 n 是序列的长度。原创 2024-10-20 15:53:29 · 353 阅读 · 0 评论 -
【状态机DP】【记忆化搜索及翻译递推】【空间优化】力扣3290. 最高乘法得分
你的得分将是 a[0] * b[i0] + a[1] * b[i1] + a[2] * b[i2] + a[3] * b[i3] 的值。我们在定义递推的状态转换方程的时候,有两种情况,选择或者不选择b[i],如果选择了b[i],那么这时候a[j]会和b[i]相乘,a[j]和b[i]都被使用了,对应。选择下标 0, 1, 2 和 5。输入: a = [3,2,5,6], b = [2,-6,4,-5,-3,2,-7]输入: a = [-1,4,5,-2], b = [-5,-1,-3,-2,-4]原创 2024-10-17 20:57:51 · 649 阅读 · 0 评论 -
【状态机DP】力扣2222. 选择建筑的方案数
比方说,给你 s = “001101” ,我们不能选择第 1 ,3 和 5 栋建筑,因为得到的子序列是 “011” ,有相邻两栋建筑是同一类型,所以 不合 题意。遍历字符串s,假设每个元素为中间元素,定义cnt为之前的1的数量,定义count为字符串中总共的1的数量,res为有效方案数的总数。当s[I]为1的时候,这种情况下的有效方案数的数量为前面的0的数量和后面的0的数量的乘积,对应代码。当s[I]为0的时候,有效方案的数量为前面的1的数量和后面1的数量的乘积,对应代码。解释:没有任何符合题意的选择。原创 2024-10-17 11:54:30 · 364 阅读 · 0 评论 -
【状态机DP】力扣2745. 构造最长的新字符串
这三个整数表示你有 x 个 “AA” 字符串,y 个 “BB” 字符串,和 z 个 “AB” 字符串。解释:我们可以按顺序连接 “AB” ,“AB” ,“AA” ,“BB” ,“AA” ,“BB” 和 “AA” ,得到新字符串 “ABABAABBAABBAA”。解释: 我们可以按顺序连接 “BB” ,“AA” ,“BB” ,“AA” ,“BB” 和 “AB” ,得到新字符串 “BBAABBAABBAB”。,如果当上一个状态不是AA,是BB或者AB的时候,那么后面可以跟AA或AB,对应。原创 2024-10-16 21:00:01 · 384 阅读 · 0 评论 -
【状态机DP】力扣3259. 超级饮料的最大强化能量
你需要每小时饮用一种能量饮料来 最大化 你的总强化能量。然而,如果从一种能量饮料切换到另一种,你需要等待一小时来梳理身体的能量体系(在那个小时里你将不会获得任何强化能量)。对于f[i][0]可以从两个状态转换而来,一种是前一天喝的是A饮料,因为喝同一种饮料没有冷冻期,还有一种是前两天喝的是B饮料,那么前一天就是冷却期,得到状态转换方程。我们定义两种状态,一种是f[i][0]代表第i-2个小时使用能量A所具有的最大能量,一种是f[i][1]代表第i-2个小时使用能量B所具有的最大能量。原创 2024-10-16 15:37:42 · 359 阅读 · 0 评论 -
【状态机DP】力扣1493. 删掉一个元素以后全为 1 的最长子数组
我们可以定义两个数组,一个pre[i]来记录以i结尾的最大连续1的数量,一个suf[i]用来记录以i开头的最大连续1的数量,然后我们遍历每个元素作为删除的元素,然后就可以知道如果删除了这个元素,那么pre[i-1]和suf[i+1]的和就是最大连续1的数量。解释:删掉位置 4 的数字后,[0,1,1,1,1,1,0,1] 的最长全 1 子数组为 [1,1,1,1,1]。假设nums = {1, 1, 0, 1, 1, 1, 0, 1, 1}输入:nums = [0,1,1,1,0,1,1,0,1]原创 2024-10-15 21:16:42 · 577 阅读 · 0 评论 -
【状态机DP】力扣714. 买卖股票的最佳时机含手续费
我们可以定义两个状态f[i][0]和f[i][1]。f[i][0]代表第i天结束后并持有股票的最大利润,f[i][1]代表第i天结束后没有持有股票的最大利润。那么f[i][0]可以从两个状态转换而来,第一种是不操作,说明前一天结束的时候就已经持有股票,第二种是第i天买入了股票,说明前一天结束的时候没有持有股票。f[I][1]也可以从两个状态转换而来,第一种是不操作,说明前一天结束的时候依旧没有持有股票,第二种是第i天卖出了股票,说明前一天结束的时候持有股票。:O(n),其中 n 为数组的长度。原创 2024-10-15 15:59:03 · 331 阅读 · 0 评论 -
【状态机DP】力扣309. 买卖股票的最佳时机含冷冻期
dp[i][2]是不持有股票但不处于冷冻期,说明我们没有进行买入或者卖出的操作,不然在第i天结束后会持有股票或者处于冷冻期。dp[i][0]代表的是持有股票,也就是第i天结束后是持有股票的。那么如何在第i天结束后持有股票呢?dp[i][1]是不持有股票且处于冷冻期,如何才能让在第i天结束的时候处于冷冻期呢?只有在第i天进行了卖的操作,那么第i-1天结束的时候,我们肯定是持有股票的,所以有。由于最后我们股票需要卖出才能获得最大收益,所以我们只要取dp[n-1][1], dp[n-1][2]两者的最大值即可。原创 2024-10-14 23:02:45 · 667 阅读 · 0 评论 -
【状态机DP】【hard】力扣188. 买卖股票的最佳时机 IV
我们定义动态数组buy[i][j],含义是在第i天的时候,持有股票(不一定是当天买)并储存最大利润,然后一共有完整的交易j次(完整的交易指的是经过买和卖)。解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2。有几个细节要注意的是,我们是从第0天而不是第一天开始,然后我们第0天的时候,不可能有完整的操作(最多进行一次买操作),所以第0天。输入:k = 2, prices = [3,2,6,5,0,3]原创 2024-10-14 17:46:51 · 1481 阅读 · 0 评论 -
【状态机DP】【hard】【字节面试题】力扣123. 买卖股票的最佳时机 III
buy1的意思是,我们可以对今天的股价选择买或者不买,买的话利润就是-prices[i],不买利润不变,我们要保证最大利润。然后sell1可以选择今天卖或者不卖,不卖的话利润不变,如果卖的话,就将买造成的负利润加上当前卖出的价格,就是我们现在的利润,我们依旧要保证第一次卖的时候,利润要最大。随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3。输入:prices = [3,3,5,0,0,3,1,4]原创 2024-10-13 18:43:39 · 411 阅读 · 0 评论 -
【动态规划-状态机 DP】力扣121. 买卖股票的最佳时机
我们假设每天都卖出,然后我们就希望在今天之前的最低价格买入,这样就会有最大的利润,每当我们发现了最小的价格,我们就假设一种情况在今天最小的价格买入,在以后的最高价格卖出,来获取今天之后可能的最大利润。每次卖出我们都要比较每次卖出的利润,记录最高利润,最后返回。解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5。为了求取股票最大利润,我们希望能尽量在最低的价格买入,在买入后的最高的价格卖出。输入:[7,1,5,3,6,4]原创 2024-10-12 16:08:34 · 243 阅读 · 0 评论 -
【动态规划-最长递增子序列(LIS)】【hard】力扣1671. 得到山形数组的最少删除次数
例如,如果当前序列为 1, 2, 3,新加入的元素也是 3,upper_bound 会找到序列末尾并在适当位置插入新的 3,从而维持非严格递增的性质。而lower_bound查找的是大于等于nums[i]的元素,所以nums[i]如果有与inc中相等的元素,会替换而不是推入,这保证了最长递增子序列是严格递增的。解释:一种方法是将下标为 0,1 和 5 的元素删除,剩余元素为 [1,5,6,3,1] ,是山形数组。输入:nums = [2,1,1,5,6,2,3,1]输入:nums = [1,3,1]原创 2024-10-09 23:08:26 · 373 阅读 · 0 评论 -
【动态规划-最长递增子序列(LIS)】力扣2826. 将三个组排序
一开始我们得到g=[1,2,4,5],然后遇到x=3,替换后g=[1,2,3,5],这时候g就是虚拟的递增子序列,因为很明显nums中没有这么一个递增子序列。接着遇到x=4,替换掉g中的5,g=[1,2,3,4,7]。最后遇到x=6,替换掉了g中的最后一个元素7,g=[1,2,3,4,6],这时候我们的最长子序列才真正变成了[1,2,3,4,6]。举个例子:nums = [1,2,4,5,3,7,4,6]输入:nums = [1,3,2,1,3,3]输入:nums = [2,2,2,2,3,3]原创 2024-10-09 17:32:19 · 768 阅读 · 0 评论 -
【动态规划-最长递增子序列(LIS)】力扣673.最长递增子序列的个数
就说明发现了更长的公共子序列,那么这个时候,我们就重置count[i]为count[j],之所以重置为count[j]是因为count[j]代表着之前以nums[j]结尾的最长公共递增子序列的个数,那么有count[j]个最长公共递增子序列再加上当前的nums[i],就有count[j]种以nums[i]结尾的最长公共递增子序列。然后再继续遍历以nums[i]结尾的最长公共递增子序列,如果发现了有相同长度的公共递增子序列,就加上这个以nums[j]结尾的最长公共子序列的数量count[j]。原创 2024-10-09 01:00:41 · 280 阅读 · 0 评论 -
【动态规划-最长公共子序列(LCS)】【hard】力扣1092. 最短公共超序列
在第一次判断的过程中,指针i指向str1的c,指针j指向str2的b,由于str1和str2的LCS是ab,那么b作为LCS的一部分,那么推入b就会影响到LCS(如果推入b后,那么构造LCS就没有意义,构造LCS的目的是让指针在都指向LCS的部分的时候,可以只推入一个元素,然后同时让i和j都-1)。str2 = “cab” 是 “cabac” 的一个子串,因为我们可以删去 “cabac” 末尾的 “ac” 得到 “cab”。输入:str1 = “aaaaaaaa”, str2 = “aaaaaaaa”原创 2024-10-08 22:31:04 · 470 阅读 · 0 评论 -
【动态规划-4.2 最长递增子序列(LIS)】力扣300. 最长递增子序列
我们需要的是len的长度,len++的来源于nums[i]大于d[len],如果d[len]被替换成更小的nums[i],会对后续的len++有正面影响,如果nums[i]替换掉的不是d[len],假设是d[len-1],那么会减小d[len-1]的值,在后续的nums[i]的替换中,会变得更容易被选为pos,从而替换d[len-1],然后对后续的len++有正面影响。由于nums[i]经过二分查找,肯定比d[pos+1]要小,所以在相同长度的子序列中,末尾最小元素就为nums[i]。:O(nlogn)。原创 2024-10-08 02:10:46 · 937 阅读 · 0 评论 -
【动态规划-最长公共子序列(LCS)】【hard】力扣1458. 两个子序列的最大点积
比方说,[2,3,5] 是 [1,2,3,4,5] 的一个子序列而 [1,5,3] 不是。这道题是LCS的变形,dp[i][j] 表示使用 nums1 的前 i 个元素和 nums2 的前 j 个元素时,能够得到的最大点积。解释:从 nums1 中得到子序列 [2,-2] ,从 nums2 中得到子序列 [3,-6]。输入:nums1 = [2,1,-2,5], nums2 = [3,0,-6]输入:nums1 = [-1,-1], nums2 = [1,1]最后返回dp[m][n]。原创 2024-10-06 21:34:49 · 555 阅读 · 0 评论 -
【动态规划-最长公共子序列(LCS)】力扣1035. 不相交的线
但无法画出第三条不相交的直线,因为从 nums1[1]=4 到 nums2[2]=4 的直线将与从 nums1[2]=2 到 nums2[1]=2 的直线相交。输入:nums1 = [2,5,1,2,5], nums2 = [10,5,2,1,5,2]输入:nums1 = [1,3,7,1,7,5], nums2 = [1,9,2,5,1]在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。输入:nums1 = [1,4,2], nums2 = [1,2,4]原创 2024-10-06 20:48:16 · 471 阅读 · 0 评论 -
【动态规划-最长公共子序列(LCS)】【hard】【科大讯飞笔试最后一题】力扣115. 不同的子序列
所以我们可以省去行的空间,只定义一个包含列的一维数组f[n],我们在循环中让j倒序,我们就有f[j-1]等同于f[i-1][j-1],f[j]等同于f[i-1][j]。如果 s[i - 1] == t[j - 1],那么 f[i][j] 既可以选择使用 s[i - 1] 来匹配 t[j - 1],也可以不使用 s[i - 1]。这个题运用了动态规划的思想,我们首先定义一个二维动态数组f[i][j],设 f[i][j] 表示字符串 s 的前 i 个字符中,子序列中 t 的前 j 个字符出现的次数。原创 2024-10-06 19:58:02 · 748 阅读 · 0 评论 -
【动态规划-最长公共子序列(LCS)】力扣97. 交错字符串
一种情况是s1的第i个字符等于s3的第i+j个字符时,要保证f[i-1][j]是否也为true,如果两个条件都满足,那么f[i][j]为true。而s1的第i个字符,在这里就是s1[i-1]。滚动数组的优化,我们观察方法一,可以观察到f[i][j]所需要参考的状态只有上面的f[i-1][j]和左边的f[i][j-1],所以我们可以使用滚动数组的方式来省略掉i。第二种情况同理,也就是s2的第j个字符等于s3的第i+j个字符,这时候也要保证f[i][j-1]也为true,f[i][j]才为true。原创 2024-10-06 18:35:56 · 722 阅读 · 0 评论 -
【编辑距离算法】力扣72. 编辑距离
首先初始化dp的边界,然后进行循环,在循环中,判断word[i-1]和word[j-1]两个字符是否相等,如果相等的话,就说明不需要进行操作,这道题的核心思路是使用动态规划,定义一个二维动态数组dp[i][j]来表示word1的前i个字符变换成word2前j个字符的最少操作次数。:O(mn),其中 m 为 word1 的长度,n 为 word2 的长度。inention -> enention (将 ‘i’ 替换为 ‘e’)如果是替换操作:dp[i-1][j-1]+1。原创 2024-10-03 17:44:17 · 464 阅读 · 0 评论 -
【动态规划-最长公共子序列(LCS)】力扣712. 两个字符串的最小ASCII删除和
最后我们计算出字符串s1和s2的ascII码之和,然后减去保留下来的相同子序列的ascII码值(需要乘以2),剩下的就是两个字符串的最小ASCII删除和。如果改为将两个字符串转换为 “lee” 或 “eet”,我们会得到 433 或 417 的结果,比答案更大。结束时,两个字符串都等于 “let”,结果即为 100+101+101+101 = 403。解释: 在 “sea” 中删除 “s” 并将 “s” 的值(115)加入总和。解释: 在 “delete” 中删除 “dee” 字符串变成 “let”,原创 2024-09-30 19:04:47 · 412 阅读 · 0 评论 -
【动态规划-最长公共子序列(LCS)】力扣583. 两个字符串的删除操作
所以可以参考力扣1143题(主页有)来求出最长公共子序列,然后最后两个字符串的长度相加,减去两倍的最长公共子序列,就是使得 word1 和 word2 相同所需的最少的删除次数。给定两个单词 word1 和 word2 ,返回使得 word1 和 word2 相同所需的最小步数。解释: 第一步将 “sea” 变为 “ea” ,第二步将 "eat "变为 “ea”输入:word1 = “leetcode”, word2 = “etco”输入: word1 = “sea”, word2 = “eat”原创 2024-09-30 16:19:22 · 431 阅读 · 0 评论 -
【线性dp-最长公共子序列(LCS)】力扣1143. 最长公共子序列
我们定义一个二维数组 dp,其中 dp[i][j] 表示 text1 的前 i 个字符与 text2 的前 j 个字符的最长公共子序列的长度。dp[i][j] 的具体含义是:text1 的前 i 个字符和 text2 的前 j 个字符的最长公共子序列的长度。一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。原创 2024-09-29 22:47:31 · 257 阅读 · 0 评论 -
【动态规划-分组背包】【hard】力扣2218. 从栈中取出 K 个硬币的最大面值和
然后j就从num_n开始向下循环到j>0,然后第三重循环w的含义是目前遍历的栈选取w+1个硬币,然后这时候更新f[j],他会比较如果选取了这个栈的前w+1个硬币,那么有没有可能会出现比之前更大的情况。输入:piles = [[100],[100],[100],[100],[100],[100],[1,1,1,1,1,1,700]], k = 7。然后定义一个整型num_n,他是用来判断j要从哪里开始向下循环,每当遍历一个栈的时候,num_n就会加上这个栈的硬币数n,然后保证不会超过k。原创 2024-09-29 21:48:48 · 451 阅读 · 0 评论 -
【动态规划-分组背包】力扣1981. 最小化目标值与所选元素的差
g[j] 表示是否可以通过选择这一行中的某些元素,使得和等于 j,也就是说g的作用是在计算完当前行的时候,赋给f,供下一行的循环使用,而f代表的是当前循环的上一行的组合可能性。实际上没错,large+x不可能比j+x小,但是有一种情况,就是当遍历的某一个元素较小的时候,而且没有j+x大于target的情况,并且同一行其他元素的x较大的时候,这时候这个较小的x的large+x就可能是最接近target的值。输入:mat = [[1,2,3],[4,5,6],[7,8,9]], target = 13。原创 2024-09-29 00:29:46 · 404 阅读 · 0 评论 -
【动态规划-分组背包】力扣1155. 掷骰子等于目标和的方法数
当我们已经确定了某个骰子i的时候,在他之前的前i-1个骰子,已经记录到了可能产生的目标和中,所以我们在计算第i个骰子可能产生的目标和的时候,是依赖于之前骰子产生的目标和。首先我们先遍历每个骰子,也就是遍历i,然后接着倒序循环从target到0的目标和,并且在每次第二层循环的时候,令dp[j] = 0,最后循环骰子可能的点数x。中,dp[j]代表的是可能产生的目标和,这取决于这次骰子的点数x,dp[j-x]取决于之前骰子产生的目标和。首先我们先定义一个向量dp[j],含义是目标和为j的时候的方案数。原创 2024-09-26 17:10:41 · 496 阅读 · 0 评论 -
【动态规划-多重背包】【hard】力扣2585. 获得分数的方法数
当我们确定某一类题目总得分t的时候,这时候方法数就是dp[j-t],我们就将之前计算的方法数dp[j]加上dp[j-t]来确定一个新的dp[j],这新的dp[j]会覆盖旧的dp[j]。输入:target = 5, types = [[50,1],[50,2],[50,5]]输入:target = 18, types = [[6,1],[3,2],[2,3]]输入:target = 6, types = [[6,1],[3,2],[2,3]]首先定义一个dp[j]向量,含义是得分为j的时候的方法数。原创 2024-09-25 19:46:55 · 1536 阅读 · 0 评论 -
【动态规划【hard】力扣1449. 数位成本和为目标值的最大数字
因为这样子,最后的字符串才会尽可能长,然后在保证了最长长度的情况下,优先使用较大的数。输入:cost = [6,10,15,40,40,40,40,40,40], target = 47。输入:cost = [7,6,5,5,5,6,8,7,8], target = 12。输入:cost = [4,3,2,5,6,7,2,5,5], target = 9。输入:cost = [2,4,6,2,4,6,4,4,4], target = 5。这个代码的目的就是记录目标值为i的时候,能用的最多数的数量。原创 2024-09-10 22:35:09 · 1395 阅读 · 0 评论 -
【完全背包】力扣518. 零钱兑换 II
这能保证在每次外层的coin循环中,组合方式的末尾都是coin,即使经过coins.size()次的循环,可以保证每个dp[j]中的组合方式都是不相同的。因为外层循环是遍历数组 coins 的值,内层循环是遍历不同的金额之和,在计算 dp[i] 的值时,可以确保金额之和等于 i 的硬币面额的顺序,由于顺序确定,因此不会重复计算不同的排列。很多人会把coin放到内层循环,这样导致的一个问题就是,会出现类似dp[3] = {1,2},{2,1},但实际上两种情况相等。请你计算并返回可以凑成总金额的硬币组合数。原创 2024-09-09 20:49:58 · 412 阅读 · 0 评论 -
【完全背包】【四平方和定理】力扣279. 完全平方数
这道题也是经典的完全背包问题,首先遍历n之前的每个数,接着计算当每个n时,遍历j,遍历 j 的目的是为了找到可以用来表示数字 i 的最少完全平方数的组合。完全平方数 是一个整数,其值等于另一个整数的平方;若要判断是否可以用两个平方和表示,那么就减去范围内任意的平方数,剩下的差要是个平方数,就说明可以。当 n=4 ^ k×(8m+7) 时,n 只能被表示为四个正整数的平方和。给你一个整数 n ,返回 和为 n 的完全平方数的最少数量。j的最少完全平方数组合,因为我们要构成的是i,所以要加上j。原创 2024-09-09 21:59:38 · 529 阅读 · 0 评论 -
【动态规划】【完全背包】力扣322. 零钱兑换
但是由于dp(coins,rem-coin)由许多种情况构成,coin可以是不同面额,那么为了凑成价值为rem金额的最小硬币数量,就要求coin要满足dp(coins,rem-coin)必须是所有coin情况的最小的硬币数量,这时候再拿一个价值为coin的硬币,才是dp(coins,rem)的最小硬币组合数。有人会好奇那么不断找到最后,会发生什么,当rem == 0的时候,也就是末节点,实际上的含义也就是凑成金额0需要0种组合,这时候他的父节点就会计算res为0,然后记录Min为res+1 = 1。原创 2024-09-06 16:30:04 · 490 阅读 · 0 评论 -
【阿里笔试题】【三维dp优化二维dp】【hard】力扣879. 盈利计划
如果选择这个工作,那么为了保证member数量的人来完成这个工作,然后剩下的j-member的人去做的工作在前i-1个项目中最少可以创造k-earn的利润,其中要注意的是dp中储存的不是恰好k利润,而是最少k利润,且题目利润没有负数,那么当k-earn小于负数的时候,为了防止数组索引出现负数越界,所以把他定义为0即可。而在三维dp中,dp[0][0][0] = 1:这意味着在没有选择任何工作的情况下,使用 0 个人,获得 0 的利润时,有一种合法的方案——即不做任何事情。总的来说,有两种计划。原创 2024-09-05 19:03:47 · 947 阅读 · 0 评论