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];
    }
}
相关推荐
東隅已逝,桑榆非晚37 分钟前
算法6. 双指针法-查找总价格为目标的两个商品
c++·学习·算法
Eyfcom1 小时前
〖物联网终端实战 01〗UWB 室内高精度定位:仓储 AGV 与人员的厘米级轨迹追踪
物联网·算法·物流系统·快递系统·跨境物流快递系统·物联网终端实战
bro_Java6662 小时前
《排序的底层逻辑:比较、交换与分治》
java·算法·排序算法
爱喝雪碧的可乐2 小时前
MATLAB
开发语言·算法·matlab
叼烟扛炮2 小时前
Linux 学习笔记(六十):单线程的逆袭——epoll 高并发服务器实战
linux·服务器·网络·笔记·学习·算法
careathers3 小时前
【数据结构】基于比较的排序算法 - 交换排序
数据结构·算法·排序算法
H.莓飛4 小时前
【C++】【STL】vector_OJ题
linux·服务器·开发语言·数据结构·c++·visual studio
Rabitebla4 小时前
【Linux操作系统】进程篇(十一):进程程序替换——从底层原理到 exec 函数族
linux·服务器·c++·笔记·学习·算法
tellmewhoisi4 小时前
深度学习0:数学知识:正态分布1
人工智能·深度学习·算法
-梅4 小时前
算法(1) 动态规划
算法·动态规划