代码随想录训练营day44| 518. 零钱兑换 II 377. 组合总和 Ⅳ

news/2024/8/22 14:37:10 标签: 动态规划, 算法

@TOC


前言

代码随想录算法训练营day44


一、Leetcode 518. 零钱兑换 II

1.题目

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。

请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。

假设每一种面额的硬币有无限个。

题目数据保证结果符合 32 位带符号整数。

示例 1:

输入:amount = 5, coins = [1, 2, 5] 输出:4 解释:有四种方式可以凑成总金额: 5=5 5=2+2+1 5=2+1+1+1 5=1+1+1+1+1

示例 2:

输入:amount = 3, coins = [2] 输出:0 解释:只用面额 2 的硬币不能凑成总金额 3 。

示例 3:

输入:amount = 10, coins = [10] 输出:1

提示:

1 <= coins.length <= 300
1 <= coins[i] <= 5000
coins 中的所有值 互不相同
0 <= amount <= 5000

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/coin-change-ii

2.解题思路

方法一:动态规划

这道题中,给定总金额 amountamount 和数组 coinscoins,要求计算金额之和等于 amountamount 的硬币组合数。其中,coinscoins 的每个元素可以选取多次,且不考虑选取元素的顺序,因此这道题需要计算的是选取硬币的组合数。

可以通过动态规划的方法计算可能的组合数。用 dp[x]dp[x] 表示金额之和等于 xx 的硬币组合数,目标是求 dp[amount]dp[amount]。

动态规划的边界是 dp[0]=1dp[0]=1。只有当不选取任何硬币时,金额之和才为 00,因此只有 11 种硬币组合。

对于面额为 coincoin 的硬币,当 coin≤i≤amountcoin≤i≤amount 时,如果存在一种硬币组合的金额之和等于 i−coini−coin,则在该硬币组合中增加一个面额为 coincoin 的硬币,即可得到一种金额之和等于 ii 的硬币组合。因此需要遍历 coinscoins,对于其中的每一种面额的硬币,更新数组 dpdp 中的每个大于或等于该面额的元素的值。

由此可以得到动态规划的做法:

初始化 dp[0]=1dp[0]=1;

遍历 coinscoins,对于其中的每个元素 coincoin,进行如下操作:
    遍历 ii 从 coincoin 到 amountamount,将 dp[i−coin]dp[i−coin] 的值加到 dp[i]dp[i]。

最终得到 dp[amount]dp[amount] 的值即为答案。

上述做法不会重复计算不同的排列。因为外层循环是遍历数组 coinscoins 的值,内层循环是遍历不同的金额之和,在计算 dp[i]dp[i] 的值时,可以确保金额之和等于 ii 的硬币面额的顺序,由于顺序确定,因此不会重复计算不同的排列。

例如,coins=[1,2]coins=[1,2],对于 dp[3]dp[3] 的计算,一定是先遍历硬币面额 11 后遍历硬币面额 22,只会出现以下 22 种组合:

3=1+1+13=1+233​=1+1+1=1+2​

硬币面额 22 不可能出现在硬币面额 11 之前,即不会重复计算 3=2+13=2+1 的情况。

3.代码实现

```java class Solution { public int change(int amount, int[] coins) { int[] dp = new int[amount + 1]; dp[0] = 1; for (int coin : coins) { for (int i = coin; i <= amount; i++) { dp[i] += dp[i - coin]; } } return dp[amount]; } }

```

二、Leetcode 377. 组合总和 Ⅳ

1.题目

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。

题目数据保证答案符合 32 位整数范围。

示例 1:

输入:nums = [1,2,3], target = 4 输出:7 解释: 所有可能的组合为: (1, 1, 1, 1) (1, 1, 2) (1, 2, 1) (1, 3) (2, 1, 1) (2, 2) (3, 1) 请注意,顺序不同的序列被视作不同的组合。

示例 2:

输入:nums = [9], target = 3 输出:0

提示:

1 <= nums.length <= 200
1 <= nums[i] <= 1000
nums 中的所有元素 互不相同
1 <= target <= 1000

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/combination-sum-iv

2.解题思路

方法一:动态规划

这道题中,给定数组 numsnums 和目标值 targettarget,要求计算从 numsnums 中选取若干个元素,使得它们的和等于 targettarget 的方案数。其中,numsnums 的每个元素可以选取多次,且需要考虑选取元素的顺序。由于需要考虑选取元素的顺序,因此这道题需要计算的是选取元素的排列数。

可以通过动态规划的方法计算可能的方案数。用 dp[x]dp[x] 表示选取的元素之和等于 xx 的方案数,目标是求 dp[target]dp[target]。

动态规划的边界是 dp[0]=1dp[0]=1。只有当不选取任何元素时,元素之和才为 00,因此只有 11 种方案。

当 1≤i≤target1≤i≤target 时,如果存在一种排列,其中的元素之和等于 ii,则该排列的最后一个元素一定是数组 numsnums 中的一个元素。假设该排列的最后一个元素是 numnum,则一定有 num≤inum≤i,对于元素之和等于 i−numi−num 的每一种排列,在最后添加 numnum 之后即可得到一个元素之和等于 ii 的排列,因此在计算 dp[i]dp[i] 时,应该计算所有的 dp[i−num]dp[i−num] 之和。

由此可以得到动态规划的做法:

初始化 dp[0]=1dp[0]=1;

遍历 ii 从 11 到 targettarget,对于每个 ii,进行如下操作:
    遍历数组 numsnums 中的每个元素 numnum,当 num≤inum≤i 时,将 dp[i−num]dp[i−num] 的值加到 dp[i]dp[i]。

最终得到 dp[target]dp[target] 的值即为答案。

上述做法是否考虑到选取元素的顺序?答案是肯定的。因为外层循环是遍历从 11 到 targettarget 的值,内层循环是遍历数组 numsnums 的值,在计算 dp[i]dp[i] 的值时,numsnums 中的每个小于等于 ii 的元素都可能作为元素之和等于 ii 的排列的最后一个元素。例如,11 和 33 都在数组 numsnums 中,计算 dp[4]dp[4] 的时候,排列的最后一个元素可以是 11 也可以是 33,因此 dp[1]dp[1] 和 dp[3]dp[3] 都会被考虑到,即不同的顺序都会被考虑到。

3.代码实现

```java class Solution { public int combinationSum4(int[] nums, int target) { int[] dp = new int[target + 1]; dp[0] = 1; for (int i = 1; i <= target; i++) { for (int num : nums) { if (num <= i) { dp[i] += dp[i - num]; } } } return dp[target]; } }

```


http://www.niftyadmin.cn/n/4957574.html

相关文章

【QML】鼠标放在控件上颜色改变的效果实现

最近刚好要用到一个功能&#xff0c;在qml上实现鼠标放上去&#xff0c;控件的颜色改变&#xff0c;鼠标移走&#xff0c;控件颜色恢复。第一反应是这个功能非常简单&#xff0c;但是搞了一会儿都没实现&#xff0c;最后发现MouseArea其实提供了一个很简便的方法来提供使用&…

自然语言处理从入门到应用——LangChain:索引(Indexes)-[检索器(Retrievers)]

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 检索器&#xff08;Retrievers&#xff09;是一个通用的接口&#xff0c;方便地将文档与语言模型结合在一起。该接口公开了一个get_relevant_documents方法&#xff0c;接受一个查询&#xff08;字符串&#xff09;并返…

【校招VIP】产品分析能力之用户画像出发

考点介绍&#xff1a; 用户行为和交互是产品经理能力的重要部分&#xff0c;在校招中&#xff0c;基于用户画像的分析题和设计题也是高频考点。 『产品分析能力之用户画像出发』相关题目及解析内容可点击文章末尾链接查看&#xff01; 一、考点题目 1. 爱奇艺中搜索关键词“…

(vue)多级表头且转为百分比显示

(vue)多级表头且转为百分比显示 <el-table-column align"center" label"近三个月数据情况"><el-table-column align"center" prop"amount" :label"tableLast[0]"><template slot-scope"{ row }"&g…

代码随想录23| 39. 组合总和 , 40.组合总和II, 131.分割回文串

39. 组合总和 题目链接/文章讲解&#xff1a;链接地址 视频讲解&#xff1a;链接地址 代码思路&#xff1a;传入的参数&#xff1a;传入的参数每层需要遍历的元素&#xff0c;目标值&#xff0c;和值&#xff0c;开始的索引。 递归结束条件&#xff1a;sum 等于target 递归遍历…

华为OD-最大括号深度

题目描述 一个合法的括号匹配序列有以下定义: 1、空串""是一个合法的括号匹配序列 2、如果"X"和"Y"都是合法的括号匹配序列,"XY"也是一个合法的括号匹配序列 3、如果"X"是一个合法的括号匹配序列,那么"(X)"也是一…

一个滚动框高度动态计算解决方案

需求描述&#xff0c;一个嵌套了很多层div或者其他标签的内容框&#xff0c;而它的外层没有设置高度&#xff0c;或者使用百分比&#xff0c;而本容器需要设置高度来实现滚动&#xff0c;要么写死px高度&#xff0c;但是不能自适应&#xff0c;此时需要一个直系父容器&#xff…

C++(7)多态

多态 polymorphism 1、父类中有虚函数 2、子类中覆写&#xff08;override&#xff09;父类的虚函数 3、子类对象的地址赋给了父类的指针&#xff0c;并通过该指针用虚函数 #include <iostream>using namespace std;class A { public:virtual void func()cout<&…