相信很多小伙伴刷题的时候面对力扣上近两千道题目,感觉无从下手,我花费半年时间整理了Github项目:leetcode刷题攻略。 里面有100多道经典算法题目刷题顺序、配有40w字的详细图解,常用算法模板总结,以及难点视频讲解,按照list一道一道刷就可以了!star支持一波吧!

周一

动态规划:377. 组合总和 Ⅳ中给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数(顺序不同的序列被视作不同的组合)。

题目面试虽然是组合,但又强调顺序不同的序列被视作不同的组合,其实这道题目求的是排列数!

递归公式:dp[i] += dp[i - nums[j]];

这个和前上周讲的组合问题又不一样,关键就体现在遍历顺序上!

在动态规划:518.零钱兑换II 中就已经讲过了。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

如果把遍历nums(物品)放在外循环,遍历target的作为内循环的话,举一个例子:计算dp[4]的时候,结果集只有 {1,3} 这样的集合,不会有{3,1}这样的集合,因为nums遍历放在外层,3只能出现在1后面!

所以本题遍历顺序最终遍历顺序:target(背包)放在外循环,将nums(物品)放在内循环,内循环从前到后遍历

class Solution {
public:int combinationSum4(vector<int>& nums, int target) {vector<int> dp(target + 1, 0);dp[0] = 1;for (int i = 0; i <= target; i++) { // 遍历背包for (int j = 0; j < nums.size(); j++) { // 遍历物品if (i - nums[j] >= 0 && dp[i] < INT_MAX - dp[i - nums[j]]) {dp[i] += dp[i - nums[j]];}}}return dp[target];}
};

周二

爬楼梯之前我们已经做过了,就是斐波那契数列,很好解,但动态规划:70. 爬楼梯进阶版(完全背包)中我们进阶了一下。

改为:每次可以爬 1 、 2、…、m 个台阶。问有多少种不同的方法可以爬到楼顶呢?

1阶,2阶,… m阶就是物品,楼顶就是背包。

每一阶可以重复使用,例如跳了1阶,还可以继续跳1阶。

问跳到楼顶有几种方法其实就是问装满背包有几种方法。

此时大家应该发现这就是一个完全背包问题了!

和昨天的题目动态规划:377. 组合总和 Ⅳ基本就是一道题了,遍历顺序也是一样一样的!

代码如下:

class Solution {
public:int climbStairs(int n) {vector<int> dp(n + 1, 0);dp[0] = 1;for (int i = 1; i <= n; i++) { // 遍历背包for (int j = 1; j <= m; j++) { // 遍历物品if (i - j >= 0) dp[i] += dp[i - j];}}return dp[n];}
};

代码中m表示最多可以爬m个台阶,代码中把m改成2就是本题70.爬楼梯可以AC的代码了。

周三

动态规划:322.零钱兑换给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数(每种硬币的数量是无限的)。

这里我们都知道这是完全背包。

递归公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);

关键看遍历顺序。

本题求钱币最小个数,那么钱币有顺序和没有顺序都可以,都不影响钱币的最小个数。

所以本题并不强调集合是组合还是排列。

那么本题的两个for循环的关系是:外层for循环遍历物品,内层for遍历背包或者外层for遍历背包,内层for循环遍历物品都是可以的!

外层for循环遍历物品,内层for遍历背包:

// 版本一
class Solution {
public:int coinChange(vector<int>& coins, int amount) {vector<int> dp(amount + 1, INT_MAX);dp[0] = 0;for (int i = 0; i < coins.size(); i++) { // 遍历物品for (int j = coins[i]; j <= amount; j++) { // 遍历背包if (dp[j - coins[i]] != INT_MAX) { // 如果dp[j - coins[i]]是初始值则跳过dp[j] = min(dp[j - coins[i]] + 1, dp[j]);}}}if (dp[amount] == INT_MAX) return -1;return dp[amount];}
};

外层for遍历背包,内层for循环遍历物品:

// 版本二
class Solution {
public:int coinChange(vector<int>& coins, int amount) {vector<int> dp(amount + 1, INT_MAX);dp[0] = 0;for (int i = 1; i <= amount; i++) {  // 遍历背包for (int j = 0; j < coins.size(); j++) { // 遍历物品if (i - coins[j] >= 0 && dp[i - coins[j]] != INT_MAX ) {dp[i] = min(dp[i - coins[j]] + 1, dp[i]);}}}if (dp[amount] == INT_MAX) return -1;return dp[amount];}
};

周四

动态规划:279.完全平方数给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少(平方数可以重复使用)。

如果按顺序把前面的文章都看了,这道题目就是简单题了。 dp[i]的定义,递推公式,初始化,遍历顺序,都是和动态规划:322. 零钱兑换 一样一样的。

要是没有前面的基础上来做这道题,那这道题目就有点难度了。

这也体现了刷题顺序的重要性

先遍历背包,在遍历物品:

// 版本一
class Solution {
public:int numSquares(int n) {vector<int> dp(n + 1, INT_MAX);dp[0] = 0;for (int i = 0; i <= n; i++) { // 遍历背包for (int j = 1; j * j <= i; j++) { // 遍历物品dp[i] = min(dp[i - j * j] + 1, dp[i]);}}return dp[n];}
};

先遍历物品,在遍历背包:

// 版本二
class Solution {
public:int numSquares(int n) {vector<int> dp(n + 1, INT_MAX);dp[0] = 0;for (int i = 1; i * i <= n; i++) { // 遍历物品for (int j = 1; j <= n; j++) { // 遍历背包if (j - i * i >= 0) {dp[j] = min(dp[j - i * i] + 1, dp[j]);}}}return dp[n];}
};

总结

本周的主题其实就是背包问题中的遍历顺序!

我这里做一下总结:

求组合数:动态规划:518.零钱兑换II
求排列数:动态规划:377. 组合总和 Ⅳ、动态规划:70. 爬楼梯进阶版(完全背包)
求最小数:动态规划:322. 零钱兑换、动态规划:279.完全平方数

此时我们就已经把完全背包的遍历顺序研究的透透的了!

就酱,学算法,认准「代码随想录」,你会发现相见恨晚!

我是程序员Carl,可以找我组队刷题,也可以在B站上找到我,关注公众号代码随想录来和上万录友一起打卡学习算法,来看看,你会发现相见恨晚!

如果感觉对你有帮助,不要吝啬给一个

「代码随想录」本周学习小结!(动态规划系列五)相关推荐

  1. 「代码家」的学习过程和学习经验分享【转】

    图灵丛书的一句话说的很好,Standing on the shoulders of giants,是的,我们一直站在巨人的肩上,我们起步都在沿着他们的轨迹前行,之后慢慢的在前人的开发基础或者规范上写出 ...

  2. 新功能又来啦!这次是「代码搜索」和视频直播!

    不知不觉又到周五,菌菌又带着新功能来啦! 代码搜索功能发布,提升开发效率 开发一个项目,配置参数是必不可少的步骤,而项目规模越大需要配置的参数就越多.怎么样?是不是已经开始头疼了?dengdengde ...

  3. 如何排版 微信公众号「代码块」之 MarkEditor

    前段时间写过一篇文章 如何排版微信公众号「代码块」,讲的是如何使用浏览器插件 Markdown Here 来排版代码块.虽然用 Markdown Here 排版出来的样式还不错,但存在一个问题,就是代 ...

  4. 「技术选型」深度学习软件如何选择?

    深度学习(DL, Deep Learning)是机器学习(ML, Machine Learning)领域中一个新的研究方向,它被引入机器学习使其更接近于最初的目标--人工智能(AI, Artifici ...

  5. 如何排版 微信公众号「代码块」

    最近博主刚开通微信公众号「石佳劼的博客」,被微信公众平台的图文编辑器折腾的不轻,如果文章中包含「代码块」,怎么排版都显得杂乱无章.之前一直用 Markdown 写作,从来没有考虑过排版.样式问题,因为 ...

  6. 「模型解读」深度学习网络只能有一个输入吗

    https://www.toutiao.com/a6711317479001424395/ 平常我们所见的深度学习模型,都是输入一个图像或者视频序列,输出分类,分割,目标检测等结果,但是还有一种模型需 ...

  7. 谷歌大脑提出对智能体进行「正向-反向」强化学习训练,加速训练过程

    原文来源:arXiv 作者:Ashley D. Edwards.Laura Downs.James C. Davidson 「雷克世界」编译:嗯~是阿童木呀.KABUDA.EVA 在强化学习问题中,关 ...

  8. 「代码家」的学习过程和学习经验分享

    每天,都会有人在微博上私信我,问我关于学习和成长的问题.这种问题我一般都不会回复某个j,毕竟每个人的情况不一样,每个人对待事物的性格也不一样,我不能夸下海口的说,你看某本书几个月就能如何如何,我能做的 ...

  9. 「代码家」的学习过程和学习经验分享(挺好的一篇文章,转载侵删)

    转自:https://kb.cnblogs.com/page/554260/ 感悟:多写多练,抓住灵感. 每天,都会有人在微博上私信我,问我关于学习和成长的问题.这种问题我一般都不会回复某个j,毕竟每 ...

  10. 本周学习小结(11/03 - 17/03)

    LeetCode LeetCode刷题. 本周主要在ML上. 学习笔记之Problem Solving with Algorithms and Data Structures using Python ...

最新文章

  1. 如何启用计算机上的无线网络连接,告诉大家win10无线网络连接如何打开
  2. Python 计算Mesh顶点法向量
  3. 私.Modbus测试_ZC01_TCP方式
  4. eclipse指定jdk版本启动,解决Version XXXX of the JVM is not
  5. 14 代码分割之lazy:Suspense与路由懒加载
  6. WPF 实现 DataGrid/ListView 分页控件
  7. java jwt 验证_教程:用Java创建和验证JWT
  8. golang map的无序性验证
  9. elementui 可伸缩侧边栏_ElementUI 侧边栏伸缩布局
  10. python 3.8.5 打包_骚操作 | Python 实现在 App 端的人脸识别
  11. cv2读取带中文路径方法
  12. pycharm 激活
  13. SqlHelper——只因为在人群中多看了你一眼
  14. ubuntu 20 解决软件商店不可用问题
  15. 射频day5:波导为什么noTEM;相速 相波长 群速 波阻抗
  16. element-ui input 身份证号码验证
  17. 怎么把视频语音转换成文字呢?
  18. 华为交换机S5735S如何堆叠iStack
  19. 内部总线(双向数据总线)
  20. 解析几何:第四章 空间中的直线与平面(1)空间直线的方向、平面方程、空间直线方程

热门文章

  1. 理解OpenCL数据类型
  2. LVS学习系列(1)--入门
  3. Action类一般情况为何要继承ActionSupport
  4. 宋体、代码-iOS网络编程实践--NSStream实现TCP Socket iPhone客户端-by小雨
  5. 第六节:变量-可变变量
  6. Oracle Sql Developer 改成英文界面
  7. getResourceAsStream方法获取资源的详解
  8. 前端基础:call,apply,bind的的理解
  9. 士兵杀敌 三 --- O( 1 ) 的时间复杂度 .
  10. [转]WebService压缩