5月23日零钱兑换+组合总和Ⅳ

377.组合总和Ⅳ

给你一个由 不同 整数组成的数组 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

思路

这道题也是经典的完全背包问题,区别在于,组成target的零钱组合的排列顺序不一样也会算进组合总数,所以这道题本质求的是排列,而之前的题目求的是总和。

首先确定dp数组,定义一个大小为amount+1的一维dp数组,dp[i]表示能够组成总和i的组合个数。dp[0]初始化为1,dp数组的递推公式为dp[j]=d[j]+dp[j-nums[i]](当j>=nums[i])

但这其实是求组合数的思路,没有考虑到顺序的问题,所以我们应该在递推过程中先遍历target再遍历nums,这样对于每一种背包大小,nums中每个小于背包大小的值都会被考虑作为元素之和=背包大小的最后一个元素,所以不同顺序都会被考虑。

代码

java 复制代码
class Solution {
public int combinationSum4(int[] nums, int target) {
        int n=nums.length;
        int[] dp=new int[target+1];
        dp[0]=1;
        for(int i=1;i<=target;i++){
            for(int j=1;j<=n;j++){
                if(i>=nums[j-1]){
                    dp[i]+=dp[i-nums[j-1]];
                }
            }
        }
        return dp[target];
    }
}

322.零钱兑换

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

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1

你可以认为每种硬币的数量是无限的。

示例 1:

输入:coins = [1, 2, 5], amount = 11
输出:3 
解释:11 = 5 + 5 + 1

示例 2:

输入:coins = [2], amount = 3
输出:-1

示例 3:

复制代码
输入:coins = [1], amount = 0
输出:0

提示:

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 231 - 1
  • 0 <= amount <= 104

思路

和474.一和零的思路差不多,区别在于这题求的是最小长度,所以需要在dp数组初始化上做一些改变。

首先定义一个一维dp数组,dp[i]表示可以凑成金额i所需的最小硬币个数。然后我们再考虑怎样初始化,首先组成金额0不需要选择任何硬币,所以dp[0]=0,然后若是要找出所需硬币的最小值,所有其它值都应该初始化为最大值+1,以便判断是否存在一种组合。

然后是递推公式,首先遍历每个硬币,然后由1到amount遍历每一个金额大小,如果金额大小大于当前硬币大小,则将dp[金额大小]更新为它与dp[金额大小-硬币面值]+1之间的较小值。最终判断dp[amount]若大于amount则返回-1,否则返回dp[amount]

代码

java 复制代码
class Solution {
    public int coinChange(int[] coins,int amount){
        int n=coins.length;
        int[] dp=new int[amount+1];
        Arrays.fill(dp,amount+1);
        dp[0]=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=amount;j++){
                if(j>=coins[i-1]){
                    dp[j]=Math.min(dp[j],dp[j-coins[i-1]]+1);
                }
            }
        }
        return dp[amount]>amount?-1:dp[amount];
    }
}
相关推荐
Tisfy2 分钟前
LeetCode 1928.规定时间内到达终点的最小花费:动态规划
算法·leetcode·动态规划·
ん贤23 分钟前
贪心算法.
算法·贪心算法
cndes31 分钟前
大数据算法的思维
大数据·算法·支持向量机
睡不着还睡不醒2 小时前
【数据结构强化】应用题打卡
算法
sp_fyf_20242 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-05
人工智能·深度学习·神经网络·算法·机器学习·语言模型·自然语言处理
C++忠实粉丝3 小时前
前缀和(6)_和可被k整除的子数组_蓝桥杯
算法
木向3 小时前
leetcode42:接雨水
开发语言·c++·算法·leetcode
TU^3 小时前
C语言习题~day16
c语言·前端·算法
吃什么芹菜卷3 小时前
深度学习:词嵌入embedding和Word2Vec
人工智能·算法·机器学习
wclass-zhengge3 小时前
数据结构与算法篇(树 - 常见术语)
数据结构·算法