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];
    }
}
相关推荐
程序员莫小特2 小时前
老题新解|大整数加法
数据结构·c++·算法
小刘max3 小时前
深入理解队列(Queue):从原理到实践的完整指南
数据结构
过往入尘土3 小时前
服务端与客户端的简单链接
人工智能·python·算法·pycharm·大模型
zycoder.3 小时前
力扣面试经典150题day1第一题(lc88),第二题(lc27)
算法·leetcode·面试
蒙奇D索大3 小时前
【数据结构】考研数据结构核心考点:二叉排序树(BST)全方位详解与代码实现
数据结构·笔记·学习·考研·算法·改行学it
洲覆4 小时前
C++ 模板、泛型与 auto 关键字
开发语言·数据结构·c++
MoRanzhi12034 小时前
15. Pandas 综合实战案例(零售数据分析)
数据结构·python·数据挖掘·数据分析·pandas·matplotlib·零售
智驱力人工智能4 小时前
工厂抽烟检测系统 智能化安全管控新方案 加油站吸烟检测技术 吸烟行为智能监测
人工智能·算法·安全·边缘计算·抽烟检测算法·工厂抽烟检测系统·吸烟监测
程序员爱钓鱼4 小时前
Go语言实战案例——进阶与部署篇:编写Makefile自动构建Go项目
后端·算法·go
_Power_Y5 小时前
Java面试常用算法api速刷
java·算法·面试