AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

LeetCode 322. Coin Change    原题链接    中等

作者: 作者的头像   yxc ,  2018-06-26 23:15:34 ,  所有人可见 ,  阅读 4316


13


3

题目描述

给定 $n$ 种不同硬币的面值,以及需要凑出的总面值 $total$。请写一个函数,求最少需要多少硬币,可以凑出 $total$ 的钱。
如果不存在任何一种拼凑方案,则返回-1。

注意:
你可以假定所有硬币都有无限多个。

样例1

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

样例2

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

算法

(动态规划) $O(nm)$

完全背包问题。
相当于有 $n$ 种物品,每种物品的体积是硬币面值,价值是1。问装满背包最少需要多少价值的物品?

状态表示: f[j] 表示凑出 $j$ 价值的钱,最少需要多少个硬币。
第一层循环枚举不同硬币,第二层循环从小到大枚举所有价值(由于每种硬币有无限多个,所以要从小到大枚举),然后用第 $i$ 种硬币更新 f[j]:f[j] = min(f[j], f[j - coins[i]] + 1)。

时间复杂度分析:令 $n$ 表示硬币种数,$m$ 表示总价钱,则总共两层循环,所以时间复杂度是 $O(nm)$。

C++ 代码

class Solution {
public:

    int INF = 1000000000;

    int coinChange(vector<int>& coins, int amount) {
        vector<int> f(amount + 1, INF);
        f[0] = 0;
        for (int i = 0; i < coins.size(); i ++ )
            for (int j = coins[i]; j <= amount; j ++ )
                f[j] = min(f[j], f[j - coins[i]] + 1);
        if (f[amount] == INF) f[amount] = -1;
        return f[amount];
    }
};

9 评论


用户头像
ttk.   2023-02-17 21:53         踩      回复

为什么二维的不能从j=coins[i]开始呢

用户头像
顾辰枫   2023-03-05 23:20      2    踩      回复

因为二维需要将f[i][j]先赋值f[i - 1][j],从coins[i]开始有的就没法赋值


用户头像
刷题找工作   2019-11-11 15:12         踩      回复

f[i] = min(f[i], f[i - coins[i]] + 1) /// f[j] = min(f[j], f[j - coins[i]] + 1)
有点问题吧

用户头像
yxc   2019-11-13 17:50         踩      回复

多谢指正,已更正~


用户头像
此题有解否   2019-04-18 13:52         踩      回复

完全背包第二层不是从小到大吗?

用户头像
yxc   2019-04-18 16:57         踩      回复

笔误了,已改hh


用户头像
johnhaxx   2018-10-20 06:02         踩      回复

“第二层循环从大到小枚举所有价值(由于每种硬币有无限多个,所以要从大到小枚举)”
无限多个应该是从小到大?

用户头像
yxc   2019-04-18 16:57         踩      回复

笔误了,已改hh


App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息