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数组,dpi表示能够组成总和i的组合个数。dp0初始化为1,dp数组的递推公式为dpj=dj+dpj-nums\[i](当j>=numsi)

但这其实是求组合数的思路,没有考虑到顺序的问题,所以我们应该在递推过程中先遍历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数组,dpi表示可以凑成金额i所需的最小硬币个数。然后我们再考虑怎样初始化,首先组成金额0不需要选择任何硬币,所以dp0=0,然后若是要找出所需硬币的最小值,所有其它值都应该初始化为最大值+1,以便判断是否存在一种组合。

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

代码

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];
    }
}
相关推荐
倒头就睡的小比特4 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼4 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
m0_547486664 天前
《数据结构教程》全套 PPT课件2026
数据结构
旖旎夜光4 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark4 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her14 天前
并查集-听课笔记
笔记·算法·并查集
码流子4 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven4 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark4 天前
从算法设计模式看编程思维的抽象能力4
算法