Leetcode刷题总结-2.动态规划篇

Leetcode刷题总结

动态规划算法刷题心得、总结


文章目录

  • Leetcode刷题总结
  • 前言
  • 一、动态规划题思路
  • 总结


前言

动态规划和贪心算法有一些相似之处,但是也有一些区别,动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,贪心算法而是从局部直接选最优的,动态规划的解法比贪心更加直观一些。


一、动态规划题思路

  1. 力扣 509 题 斐波那契数、70题 爬楼梯, https://leetcode.cn/problems/fibonacci-number/ 、 https://leetcode.cn/problems/climbing-stairs/ ;
    思路:这两道题都是比较简单的题,题中都比较明显的告诉了递推公式:dp[i] = dp[i-1] + dp[i-2],那么只需看下初始化的时候把初始化整清楚,遍历顺序正确即可。

  2. 力扣 746 题 使用最小花费爬楼梯, https://leetcode.cn/problems/min-cost-climbing-stairs/ ;
    思路:这道题在爬楼梯的基础上加上了怕每个楼梯的代价,递推公式也比较明显:dp[i] = min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2]),就是在走一步和走两步之间选择代价比较小的走。

  3. 力扣 62 题 不同路径、63题 不同路径 II, https://leetcode.cn/problems/unique-paths/、 https://leetcode.cn/problems/unique-paths-ii/ ;
    思路:第一道题不同路径的思路就是当前节点的路径数等于它上方的节点的路径数加上左方的节点的路径数,即dp[j][i] = dp[j-1][i] + dp[j][i-1],需要注意的是初始化的时候第一行、第一列都需要初始化为1,因为沿着第一行或者第一列一直往下走一直都是同一种路径;第一道题不同路径II的区别在于有些节点有障碍,此时有一个坑就是 初始化第一行、第一列的时候并不是当前节点存在障碍就仅仅把它在dp数组中的值记为0,而是往后的都需要为0,这个问题解决后,在给dp[j][i]赋值时,只需要判断它是否为0(为0,表示不存在障碍),如果为0,再去计算,即dp[j][i] = dp[j-1][i] + dp[j][i-1]即可。

  4. 力扣 343 题 整数拆分, https://leetcode.cn/problems/integer-break/;
    思路:这道题的思路就是把dp数组定义为当前的数i拆分后的最大乘积,有一个坑就是 dp[i - j] * dp[j],我刚开始就把递推公式想成了这个,但这个是不对的,因为这相当于把当前的数至少拆分为了四个数,因为dp[i]都至少拆分为两个数是题目的要求,所以这点很容易搞错,正确的递归公式应该是dp[i] = max(dp[i], max((i - j) * j, dp[i-j] * j));(i - j) * j代表了拆分为两个数,后面的dp[i-j] * j代表拆分为三个以及以上的数。

  5. 力扣 96 题 不同的二叉搜索树, https://leetcode.cn/problems/unique-binary-search-trees/ ;
    思路:这道题是一道比较困难的题,需要自己去找规律才能找到递推公式,主要思路其实就是在dp数组中,遍历到dp[i]的时候,从0到i都可以当做根节点,用j遍历0到i,因为是二叉搜索树,所以左边的节点数为j-1,而右边的节点数位j-i,所以递推公式就是dp[i] += dp[j-1] * dp[i-j]。

  6. 力扣 416题 分割等和子集, https://leetcode.cn/problems/partition-equal-subset-sum/;
    思路:这道题的思路比较巧妙 ,题目中让你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等,实际上你只需要把所有的元素加起来求和,然后把sum值除以2,看这个数组能否凑出来sum/2的和,如果可以那就输出True否则输出False

  7. 力扣 1049 题 最后一块石头的重量 II, https://leetcode.cn/problems/last-stone-weight-ii/ ;
    思路:题目中说从数组中选出任意两块石头,然后将它们一起粉碎,新石头重量为两者差值,在最后,最多只会剩下一块石头,需要返回此石头最小的可能重量,看起来同样也是很难做,实际上也是求出所有石头相加的重量,然后把sum值除以2,尽量凑出重量和sum/2相近的一堆石头,另一堆石头的重量就是sum - sum/2,两堆石头的重量相减得到的就是最后一块石头的重量。

  8. 力扣 494 题 目标和, https://leetcode.cn/problems/target-sum/;
    思路:向数组中的每个整数前添加 ‘+’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 ,题目想要求的是返回通过上述方法构造的、运算结果等于 target 的不同 表达式的数目,这道题使用二维dp数组的方法想了半天还是不对,改用一维动态数组吧;这道题的思路也是比较巧妙,把数字前面是‘+’号的分为一堆,另一堆是前面为‘-’的,前者减后者等于target,也就是left - (sum - left) = target 推导出 left = (target + sum)/2,left就是数字前面是‘+’号的,right是数字前面是‘-’号的;最后就变成了能否装满背包容量为left的数组,dp[i]的递推公式为dp[j] += dp[j-nums[i]]。

  9. 力扣 474 题 一和零, https://leetcode.cn/problems/ones-and-zeroes/;
    思路:给你一个二进制字符串数组 strs 和两个整数 m 和 n ,请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1,这道题的思路也很难想,就是i、j分别表示i个0、j个1,dp[i][j]表示有i个0、j个1的背包最多能装的字符串的个数,那么dp[i][j] = max(dp[i][j], dp[i-zeroNum][j-oneNum] + 1),zeroNum、oneNum表示该字符串种0、1的个数。

  10. 力扣 435 题 零钱兑换 II, https://leetcode.cn/problems/coin-change-ii/;
    思路:题目中给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额,让你计算并返回可以凑成总金额的硬币组合数(每种硬币有无限个)。如果任何硬币组合都无法凑出总金额,返回 0;这个是很典型的动态规划题,而且是完全背包题,但是它求的是方法数,而且是组合问题, 请记住组合问题只能先遍历物品再遍历背包,这是我写错了代码分析好久发现的呜呜,求排列问题是先遍历背包再遍历物品;而且方法类的题目都是用这个递推公式,dp[j] += dp[j - nums[i]];组合问题在遍历0-1背包的时候要倒序遍历,防止添加多次同一个物品,而完全背包求组合数时不需要倒序,这道题是完全背包求组合数,知道上面的这些,题很好解。

  11. 力扣 377 题组合总和 Ⅳ, https://leetcode.cn/problems/combination-sum-iv/;
    思路:题目描述中给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target ,让你从 nums 中找出并返回总和为 target 的元素组合的个数,这道题的题目明确说了求排列问题,所以需要先遍历背包再遍历物品,但是这个题有一个很坑的地方跟其他题不同,要检查dp[i] + dp[i - nums[j]] < INT_MAX 这个操作,否则会超过题目的32位整数范围,这点我没想到,找了半天问题也没找到,最后网上看了一下解答才发现的。

  12. 力扣 322 题 零钱兑换, https://leetcode.cn/problems/coin-change/;
    思路:题目描述中给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额,让你计算并返回可以凑成总金额所需的最少的硬币个数(每种硬币个数无限),如果没有任何一种硬币组合能组成总金额,返回 -1;这道题是很典型的完全背包问题,那么我们就按照自己熟悉的套路来,先遍历物品再遍历背包,但是本题也有一个坑吗,就是既然求最小的硬币个数,就不能初始化为0,如果初始化为INT32_MAX,那么需要在递推公式dp[j] = min(dp[j], dp[j-coins[i]] + 1)之前判断dp[j-coins[i]]是否为INT32_MAX,如果不是才能加1,否则会造成越界的问题。

  13. 力扣 279 题 完全平方数,https://leetcode.cn/problems/perfect-squares/;
    思路:题目描述中给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 ,完全平方数是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积,1、4、9 和 16 都是完全平方数;那么这道题的思路也是和零钱兑换十分的相像,就是一个完全背包问题求最小完全平方数的个数的问题,思路跟上一题类似,唯一区别在于dp[j] = min(dp[j], dp[j-ii] + 1),也就是硬币的重量是ii了,没有其他的区别。

  14. 力扣 139 题 单词拆分,https://leetcode.cn/problems/word-break/;
    思路:题目描述中给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s (不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用);这就是一个完全背包问题,而且给定的字符串s必须由固定顺序的单词才能构成,所以这是一个求排列数的问题,所以需要先遍历背包后遍历物品,物品就是当前下标0到下标i的所有字符,然后判断在字符串s中能否找到该字符,如果找打了dp[i]=true,这里的dp数组是布尔类型的,最后返回dp[s.size()]即可。

  15. 力扣 198 题 打家劫舍、213题 打家劫舍II,https://leetcode.cn/problems/house-robber/submissions/ 、https://leetcode.cn/problems/house-robber-ii/submissions/;
    思路:打家劫舍题目描述中说小偷计划偷窃沿街的房屋,相邻的房屋不能偷窃,让你求出一夜之内能够偷窃到的最高金额;打家劫舍II的不同之处就是房屋连成了环,即第一个房间和最后一个房间相邻;打家劫舍使用动态规划还是比较简单的,也就是当前偷的最大金额等于上一个房屋偷的最大金额、上上个房屋偷的最大金额和当前屋子金额相加,两者中的较大值;递推公式就是dp[i] = max(dp[i-1], dp[i-2]+nums[i]);房屋连成环,只需要 把不考虑第一个房屋和不考虑最后一个房屋当成两个要偷的区域求最大偷的金额,两者再取最大值即可。

  16. 力扣 337 题 打家劫舍III,https://leetcode.cn/problems/house-robber-iii/submissions/;
    思路:打家劫舍III有点难了,房屋连接成了一颗树,我们的思路就是dp[0]、dp[1]分别表示偷与不偷当前节点(也就是房屋)的金额,因为最后到达根节点才知道结果,所以需要用后序遍历,然后用递归得到的值传给上一层的节点,去累加值,最后到达根节点的时候就求出了最大的金额。

  17. 力扣 121 题 买卖股票的最佳时机、122题 买卖股票的最佳时机II、123题 买卖股票的最佳时机 III 、188题 买卖股票的最佳时机 IV,https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/、https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/submissions/、https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/、https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/;
    思路:买卖股票的最佳时机这四道题都是让你求能够获得的最大的利润,但是它们有一定的区别,第一道题是只买卖一次股票,第二题多次买卖股票(不限制买卖的次数)、第三题买卖股票两次、第四题买卖股票k次,dp数组的定义都是类似的dp[i][0]、dp[i][1]分别表示持有股票和不持有股票的状态,那么第一题的递推公式就是dp[i][0] = max(dp[i-1][0], -prices[i])、dp[i][1] = max(dp[i-1][1], dp[i-1][0]+prices[i]),第二题在持有股票的时候就需要改一下递推公式,dp[i][0] = max(dp[i-1][0], dp[i-1][1]-prices[i]),第三和第四题我没想出来咋做,看完解答才知道,就是用2k+1个状态表示k次买卖,i=1、i=2表示第一次持有股票和第一次不持有股票,往后就是类推即可,那么二维dp数组的长度就是股票的长度(列数),宽度就是2k+1(行数),在i为奇数的时候,递推公式就是dp[i][j] = max(dp[i-1][j], dp[i-1][j-1]-prices[i]);为偶数的时候,dp[i][j] = max(dp[i-1][j], dp[i-1][j-1]+prices[i]);股票买卖问题即可解决。

  18. 力扣 309 题 最佳买卖股票时机含冷冻期,https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/;
    思路:题目描述中给你一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。​
    让你设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票),其中在卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天);这道题的思路也是十分的巧妙不好想,既然有冷冻期我们就要把保持卖出的状态拆开,拆为冷冻期和保持卖出的状态,同时为了递推公式更好理解把保持卖出的状态拆分为卖出状态和保持卖出的状态,就是哪天卖出从保持卖出状态中拆分出来,所以就是四个状态。二维dp数组的递推公式为:dp[i][0] = max(max(dp[i-1][0], dp[i-1][3]-prices[i]), dp[i-1][1]-prices[i]); dp[i][1] = max(dp[i-1][1], dp[i-1][3]);dp[i][2] = dp[i-1][0]+prices[i]; dp[i][3] = dp[i-1][2];最后求max(max(dp[prices.size()-1][1], dp[prices.size()-1][2]), dp[prices.size()-1][3])。

  19. 力扣 714 题 买卖股票的最佳时机含手续费,https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/;
    思路:题目描述中给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用(你可以无限次地完成交易);那么这道题和买卖股票的最佳时机II基本相同,只是在每次计算利润的时候减去手续费即可,递推公式为dp[i][0] = max(dp[i-1][0],dp[i-1][1] -prices[i])、dp[i][1] = max(dp[i-1][1], dp[i-1][0]+prices[i]-fee)。

  20. 力扣 300 题 最长递增子序列,https://leetcode.cn/problems/longest-increasing-subsequence/;
    思路:题目描述中给你一个整数数组 nums ,找到其中最长严格递增子序列的长度;子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序;这道题目我选择用一维dp数组来解决,dp[i]表示从下标0到下标i的最长递增子序列;首先来看递推公式:在一个变量i遍历到下标i的时候,我们需要另一个变量j从下标0遍历到下标i-1,这样就可以把下标i对应的数字与之前的所有的子序列再构成子序列,再比较j与i对应的数字是否相同,所以递推公式为:dp[i] = max(dp[i], dp[j]+1);第二步初始化的时候要初始化为1,假设递增子序列长度为1,因为只要有数字,递增子序列长度最短为1。

  21. 力扣 674 题 最长连续递增序列, https://leetcode.cn/problems/longest-continuous-increasing-subsequence/;
    思路:这道题与300 题 最长递增子序列的区别就是要求的是连续递增的子序列,而300题没有要求连续递增;思路也是类似的,只是dp[i]的状态推导公式有些不同,因为dp[i]表示最长连续递增的子序列长度,所以如果下标i的值大于下标i-1的值,就由dp[i-1]推导而来;所以递推公式就是if(nums[i] > nums[i-1]) dp[i] = dp[i-1] + 1;初始化的时候也都是初始化为1即可,与上题类似。

  22. 力扣 718 题 最长重复子数组, https://leetcode.cn/problems/maximum-length-of-repeated-subarray/;
    思路:题目描述中给两个整数数组 nums1 和 nums2 ,让你计算两个数组中公共的 、长度最长的子数组的长度;这道题目和674 题 最长连续递增序列类似,只是让你求的是两个数组的最长重复子数组,状态的推导类似,这道题目需要用二维dp数组dp[i][j]表示 第一个数组从0到i-1下标,第二个数组从0到j-1下标的最长重复子数组,是由dp[i-1][j-1]推导而来,与674 题类似都是由左上方推导而来;递推公式为:if(nums1[i] == nums2[j]) dp[i][j] = dp[i-1][j-1] + 1;初始化的时候就要初始化为0了;
    这里说一下为什么dp[i][j]表示 第一个数组从0到i-1下标,第二个数组从0到j-1下标的最长重复子数组,因为这样我们相当于多加了在二维数组外头多加一行和一列,就不需要初始化第一行、第一列了。

  23. 力扣 1143 题 最长公共子序列, https://leetcode.cn/problems/longest-common-subsequence/;
    思路:题目描述中给两个整数数组 nums1 和 nums2 ,让你求两个数组中公共的 、长度最长的子数组的长度,这道题跟300题 最长递增子序列类似,如果nums1[i]== nums2[j],那就从左上方推导而来,如果不相等就从左侧和上边较大的值推导而来;推导公式为:nums1[i]== nums2[j]就是 dp[i][j] = dp[i-1][j-1]+1;不相等的时候就是dp[i][j] = max(dp[i][j-1], dp[i-1][j])。

  24. 力扣 1035 题 不相交的线, https://leetcode.cn/problems/uncrossed-lines/;
    思路:题目描述中给两个数组 nums1 和 nums2 ,绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线,这些直线不能相交;这看似不知道无从下手,实际上是让你求最大公共子序列的长度(不要求连续),所以递推公式为if(nums1[i-1] == nums2[j-1]) dp[i][j] = dp[i-1][j-1] + 1;否则 dp[i][j] = max(dp[i-1][j], dp[i][j-1])。

  25. 力扣 53 题最大子序列和, https://leetcode.cn/problems/maximum-subarray/;
    思路:题目描述中给你一个整数数组 nums ,让你找出一个具有最大和的连续子数组并返回其最大和;这道题其实和最长连续递增序列很类似,递推公式为dp[i] = max(nums[i], dp[i-1]+nums[i])。

  26. 力扣 115 题 不同的子序列, https://leetcode.cn/problems/distinct-subsequences/;
    思路:题目描述中给你两个字符串 s 和 t ,让你统计并返回在 s 的 子序列 中 t 出现的个数;这道题目数据编辑距离类的题目,dp[i][j]表示字符串s从0到i-1下标的s子序列中出现字符串t从0到j-1下标的t的子序列的个数,dp[i][j]如果是s[i-1]==t[j-1],那么dp[i][j]的状态由dp[i-1][j-1]和dp[i-1][j]推导出来,相当于是两个字符相同的时候考虑用该字符和不用该字符的个数相加;不相等的时候就是由dp[i-1][j]推导而来的。

  27. 力扣 583 题 两个字符串的删除操作, https://leetcode.cn/problems/delete-operation-for-two-strings/;
    思路:题目描述中给定两个单词 word1 和 word2 ,让你返回使得 word1 和 word2 相同所需的最小步数,
    每步可以删除任意一个字符串中的一个字符;这道题其实就是去找最长连续的公共子序列,那就和前面的集体很像了,dp[i][j]的含义就不再赘述了,dp[i][j]是由dp[i-1][j-1]推导而来的,如果找到了相等的字符dp[i][j]=dp[i-1][j-1]+1;否则dp[i][j]=max(dp[i-1][j],dp[i][j-1]),也就是两个字符不相等的时候就看把它之前的连续的公共子序列最大长度赋值给即可。

  28. 力扣 72 题编辑距离, https://leetcode.cn/problems/edit-distance/;
    思路:题目描述中给你两个单词 word1 和 word2, 让你返回将 word1 转换成 word2 所使用的最少操作数
    你可以对一个单词进行如下三种操作:插入一个字符、删除一个字符、替换一个字符;其实这三种操作不是都要用上,如果要求两个单词相等的最小操作次数,可以删除、替换或者插入、删除操作,我们就删除和替换吧,if(nums1[i-1] == nums2[j-1]) dp[i][j] = dp[i-1][j-1],因为相等的时候不需要操作;两个字符不相等的时候就麻烦一些了, 可以把第一个字符串的字符删掉、第二个字符串的字符删掉、把第一或者第二个字符串的该字符替换,让它们两个相同,dp[i-1][j]+1、dp[i][j-1]+1、dp[i-1][j-1]+1三者取最小值即可。

  29. 力扣 647 题 回文子串, https://leetcode.cn/problems/palindromic-substrings/;
    思路:题目描述中给你一个字符串 s ,让你统计并返回这个字符串中回文子串(回文字符串是正着读和倒过来读一样的字符串)的数目;这道题还是比较有意思的,如果你直接把题目要求的回文字符串的数目定义为dp数组的含义会发现找不到递推公式,所以这道题不能直接用题目要求的东西去定义dp数组;这道题dp数组dp[i][j]定义为范围i-j范围的子串是不是回文子串,数组的值是布尔类型的,那么我们怎么从其他状态推导出dp[i][j]的状态呢,那就需要看j和i的差距了,如果两者差距小于等于1,说明子串为一个或两个字符,如果相等的话,dp[i][j]就为true;但是,如果两者差距大于1,说明子串为三个及以上字符,那就需要同时判断dp[i+1][j-1]的状态了,dp[i+1][j-1]如果为true而且i和j下标对应的字符串相等,dp[i][j]就为true;我们这里是从最后开始遍历,这样能用到前面的结果。

  30. 力扣 516 题 最长回文子序列, https://leetcode.cn/problems/longest-palindromic-subsequence/;
    思路:题目描述中给你一个字符串 s ,让你找出其中最长的回文子序列,并返回该序列的长度;这道题目跟上一道题有点像,但不太一样;既然需要求最长的回文子序列长度,那么就让dp[i][j]表示i-j范围内最长的回文子序列长度,首先对角线都需要初始化为1,因为那里表示单个字符,一定是回文子串;那么我们就让j从i+1开始往后遍历,如果i、j对应下标相等就等于左下角的值加2;否则就等于左边和上边中较大的值。
    下面来说一说单调栈的题目,也是比较有意思的。

  31. 力扣 739 题 每日温度, https://leetcode.cn/problems/longest-palindromic-subsequence/;
    思路:题目描述中给定一个整数数组 temperatures ,表示每天的温度,让你返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天(如果气温在这之后都不会升高,请在该位置用 0 来代替);这道题也是单调栈解决的经典题目,既然要求右边更大的数,那么我们就需要让单调栈从栈口到栈底保持单调递增(因为保持单调递增才能让较大的数存在单调栈里面,如果是单调递减就无法找右边大的数了);如果当前遍历的下标对应的值比栈口大就该收获结果了(因为栈口元素比当前元素小,已经找到结果了),把栈口元素对应的下标的result数组的值赋为栈口元素下标减去当前遍历元素的下标,把栈口元素出栈;反之就把当前下标入栈,遍历完后最后返回result数组(该数组和数组的大小一样)。

  32. 力扣 496 题 下一个更大元素 I, https://leetcode.cn/problems/longest-palindromic-subsequence/;
    思路:题目描述中nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置右侧的 第一个 比 x 大的元素,给你两个没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集,对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 ,如果不存在下一个更大元素,那么本次查询的答案是 -1 ,让你返回一个长度为 nums1.length 的数组 ans 作为答案;nums1数组是nums2的子集,所以我们需要在nums2数组找比nums1数组里数更大的数时,需要先把nums1数组的数用映射存储下来,键为数值,值为对应的下标;后面遍历的过程和每日温度是一样的;如果当前遍历的下标对应的值比栈口小就入栈,如果当前遍历的下标对应的值比栈口大就需要看nums1数组里有没有栈口元素了,如果判断为有该元素,那就把result数组对应的下标赋值为大的元素,然后出栈该元素,出栈后继续比较,没有大的了就入栈。

  33. 力扣 503 题 下一个更大元素 II, https://leetcode.cn/problems/next-greater-element-ii/submissions/;
    思路:题目描述和下一个更大元素 I 类似,但是这次变成了循环找比它大的元素了,也就是形成了环;那么思路就很巧妙了,我在数组后面再加一个该数组,然后result数组也是2倍的该数组大小,按照前面的步骤计算完后再把result数组resize回数组的大小。

总结

本文主要是分享动态规划算法求解问题的思路,动态规划算法的题目一般需要找到dp数组的含义、递推公式、初始化数组、遍历顺序几个步骤。

你可能感兴趣的:(leetcode,动态规划)