算法训练 | 动态规划Part5 | 518.零钱兑换 II、377.组合总和 Ⅳ 、70.爬楼梯 (进阶)

本文主要是介绍算法训练 | 动态规划Part5 | 518.零钱兑换 II、377.组合总和 Ⅳ 、70.爬楼梯 (进阶),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

518. 零钱兑换 II

动态规划法

377. 组合总和 Ⅳ

动态规划法

70. 爬楼梯 (进阶)

动态规划法


518. 零钱兑换 II

  • 题目链接:518. 零钱兑换 II - 力扣(LeetCode)

  • 文章讲解:代码随想录

动态规划法
  • 完全背包:01背包内嵌的循环是从大到小遍历,为了保证每个物品仅被添加一次。而完全背包的物品是可以添加多次的,所以要从小到大去遍历

  • 解题思路

      但本题和纯完全背包不一样,纯完全背包是凑成背包最大价值是多少,而本题是要求凑成总金额的物品组合个数!注意题目描述中是凑成总金额的硬币组合数,组合不强调元素之间的顺序,排列强调元素之间的顺序。

  • 解题步骤

    • 确定dp数组以及下标的含义:dp[j]凑成总金额j的货币组合数为dp[j]

    • dp[j] 就是所有的dp[j - coins[i]](考虑coins[i]的情况)相加。所以递推公式:dp[j] += dp[j - coins[i]];

    • dp数组如何初始化:首先dp[0]一定要为1,dp[0] = 1是 递归公式的基础。如果dp[0] = 0 的话,后面所有推导出来的值都是0了。

    • 确定遍历顺序:本题中我们是外层for循环遍历物品(钱币),内层for遍历背包(金钱总额)。这种遍历顺序中dp[j]里计算的是组合数。如果把两个for交换顺序,此时dp[j]里算出来的就是排列数。

    • 举例推导dp数组:

  • 代码一:动态规划

// 时间复杂度: O(mn),其中 m 是amount,n 是 coins 的长度
// 空间复杂度: O(m)
class Solution {
public:int change(int amount, vector<int>& coins) {vector<int> dp(amount + 1, 0);dp[0] = 1;for (int i = 0; i < coins.size(); i++) { // 遍历物品for (int j = coins[i]; j <= amount; j++) { // 遍历背包dp[j] += dp[j - coins[i]];}}return dp[amount];}
};

377. 组合总和 Ⅳ

  • 题目链接:377. 组合总和 Ⅳ - 力扣(LeetCode)

  • 文章讲解:代码随想录

动态规划法
  • 解题思路

    • 本题题目描述说是求组合,但又说是可以元素相同顺序不同的组合算两个组合,其实就是求排列!

  • 解题步骤

    • 确定dp数组以及下标的含义:dp[i]: 凑成目标正整数为i的排列个数为dp[i]

    • 确定递推公式:dp[i](考虑nums[j])可以由 dp[i - nums[j]](不考虑nums[j]) 推导出来。因为只要得到nums[j],排列个数dp[i - nums[j]],就是dp[i]的一部分。求装满背包有几种方法,递推公式一般都是dp[i] += dp[i - nums[j]];

    • 个数可以不限使用,说明这是一个完全背包。得到的集合是排列,说明需要考虑元素之间的顺序。所以本题遍历顺序最终遍历顺序:target(背包)放在外循环,将nums(物品)放在内循环,内循环从前到后遍历。

    • 举例来推导dp数组:

  • 代码一:动态规划

// 时间复杂度: O(target * n),其中 n 为 nums 的长度
// 空间复杂度: O(target)
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. 爬楼梯 (进阶)

  • 题目链接:57. 爬楼梯(第八期模拟笔试)

  • 文章讲解:代码随想录

动态规划法
  • 解题思路

      一步一个台阶,两个台阶,三个台阶,.......,直到 m个台阶。问有多少种不同的方法可以爬到楼顶呢?这又有难度了,这其实是一个完全背包问题。1阶,2阶,.... m阶就是物品,楼顶就是背包。每一阶可以重复使用,例如跳了1阶,还可以继续跳1阶。问跳到楼顶有几种方法其实就是问装满背包有几种方法。

  • 解题步骤

    • 确定dp数组以及下标的含义:dp[i]:爬到有i个台阶的楼顶,有dp[i]种方法。

    • dp数组如何初始化:既然递归公式是 dp[i] += dp[i - j],那么dp[0] 一定为1,dp[0]是递归中一切数值的基础所在,如果dp[0]是0的话,其他数值都是0了。下标非0的dp[i]初始化为0,因为dp[i]是靠dp[i-j]累计上来的,dp[i]本身为0这样才不会影响结果。

    • 确定遍历顺序:这是背包里求排列问题,即:1、2 步 和 2、1 步都是上三个台阶,但是这两种方法不一样!所以需将target放在外循环,将nums放在内循环。每一步可以走多次,这是完全背包,内循环需要从前向后遍历。

  • 代码一:动态规划

// 时间复杂度: O(n * m)
// 空间复杂度: O(n)
#include <iostream>
#include <vector>
using namespace std;
int main() {int n, m;while (cin >> n >> m) {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];}}cout << dp[n] << endl;}
}

这篇关于算法训练 | 动态规划Part5 | 518.零钱兑换 II、377.组合总和 Ⅳ 、70.爬楼梯 (进阶)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1075786

相关文章

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

从入门到进阶讲解Python自动化Playwright实战指南

《从入门到进阶讲解Python自动化Playwright实战指南》Playwright是针对Python语言的纯自动化工具,它可以通过单个API自动执行Chromium,Firefox和WebKit... 目录Playwright 简介核心优势安装步骤观点与案例结合Playwright 核心功能从零开始学习

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

springboot如何通过http动态操作xxl-job任务

《springboot如何通过http动态操作xxl-job任务》:本文主要介绍springboot如何通过http动态操作xxl-job任务的问题,具有很好的参考价值,希望对大家有所帮助,如有错... 目录springboot通过http动态操作xxl-job任务一、maven依赖二、配置文件三、xxl-

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

Java调用C#动态库的三种方法详解

《Java调用C#动态库的三种方法详解》在这个多语言编程的时代,Java和C#就像两位才华横溢的舞者,各自在不同的舞台上展现着独特的魅力,然而,当它们携手合作时,又会碰撞出怎样绚丽的火花呢?今天,我们... 目录方法1:C++/CLI搭建桥梁——Java ↔ C# 的“翻译官”步骤1:创建C#类库(.NET

MyBatis编写嵌套子查询的动态SQL实践详解

《MyBatis编写嵌套子查询的动态SQL实践详解》在Java生态中,MyBatis作为一款优秀的ORM框架,广泛应用于数据库操作,本文将深入探讨如何在MyBatis中编写嵌套子查询的动态SQL,并结... 目录一、Myhttp://www.chinasem.cnBATis动态SQL的核心优势1. 灵活性与可