2952. 需要添加的硬币的最小数量

24 篇文章 0 订阅
12 篇文章 0 订阅

题目:

给你一个下标从 0 开始的整数数组 coins,表示可用的硬币的面值,以及一个整数 target 。

如果存在某个 coins 的子序列总和为 x,那么整数 x 就是一个 可取得的金额 。

返回需要添加到数组中的 任意面值 硬币的 最小数量 ,使范围 [1, target] 内的每个整数都属于 可取得的金额 。

数组的 子序列 是通过删除原始数组的一些(可能不删除)元素而形成的新的 非空 数组,删除过程不会改变剩余元素的相对位置。

示例 1:

输入:coins = [1,4,10], target = 19
输出:2
解释:需要添加面值为 2 和 8 的硬币各一枚,得到硬币数组 [1,2,4,8,10] 。
可以证明从 1 到 19 的所有整数都可由数组中的硬币组合得到,且需要添加到数组中的硬币数目最小为 2 。

示例 2:

输入:coins = [1,4,10,5,7,19], target = 19
输出:1
解释:只需要添加一枚面值为 2 的硬币,得到硬币数组 [1,2,4,5,7,10,19] 。
可以证明从 1 到 19 的所有整数都可由数组中的硬币组合得到,且需要添加到数组中的硬币数目最小为 1 。
示例 3:

输入:coins = [1,1,1], target = 20
输出:3
解释:
需要添加面值为 4 、8 和 16 的硬币各一枚,得到硬币数组 [1,1,1,4,8,16] 。
可以证明从 1 到 20 的所有整数都可由数组中的硬币组合得到,且需要添加到数组中的硬币数目最小为 3 。

题意:

给出一个整数数组coins,给出一个整数target,可以任选coins中任意数量的硬币来获得总面值,目标是得到 [1 , target]内所有面值,如果现有的coins中无法得到某一数值,可以向coins中加入任意面值的硬币来达到该面值,问最少可以向coins中加入几个硬币。

思路:

首先我们容易想到的是将所有硬币从小到大排序,然后从小到大的往里面加硬币。因为他要求的是最少加入几个硬币,如果我们先加入大的硬币的话,可能存在某个小的面值我们仍然无法得到,先加小硬币的话,小面值一定可以满足,大面值可能会通过加和得到满足,如果等遍历到它还无法满足再进行加入。

这就完成了我们贪心的第一步。

确定了从小面值开始加,那接下来的问题就是,我加入了一枚硬币后,怎么才能知道当前都可以得到哪些面值,怎么才能知道下一个硬币需要加多大面值的呢?

这个时候就需要我们的贪心第二步。

假设你有面值为x的硬币,面值 [1,x-1] 你都可以通过前面的硬币得到,那么加入面值x的硬币后,面值范围就变成了 [1+x , 2x-1] , 而面值 [1,x-1] 和 x 你都是可以得到的,所以你能得到的总价值就变成了 [1 , 2x-1] 。

ok,知道了这个特点,我们就开始从小面值开始遍历coins,看看我们需要加几个硬币。
x是我们要加的面值从1开始,这里要注意的是,x不只是我们要加的硬币的数值,还指x以内的面值已经都可以得到了,即 [1,x-1]都可以得到。

如果coins[i] ≤ x,说明当前这个硬币其实是多出来的,因为我们刚才已经说了,x指的是当前 [ 1 , x-1 ] 都是可以得到的,说明在遍历到coins[i]之前就已经可以得到[1 , x-1] ,那加了coins[i]后,可以得到的面值就变成了[1,x+coins[i]-1],所以x的值就更新为x+coins[i]。

如果coins[i] > x,说明x需要被我们加入。因为我们现在可以得到的面值是 [1,x-1],而当前的coins[i]是大于x的,说明x如果我们不加入的话,是永远得不到的。所以加入x,那我们可以得到的面值就变成了 [1,2x-1],所以x更新为2x-1。

这样进行下去,当x的值更新到>=target的时候,说明 [1 , target]都可以得到了,跳出循环得到答案。

代码:

class Solution {
public:
    int minimumAddedCoins(vector<int>& coins, int target) {
        sort(coins.begin() , coins.end());
        int ans = 0;
        int x = 1;
        int n = coins.size();
        int index = 0;
        while(x <= target){
            if(index < n && coins[index] <= x){
                x += coins[index];
                index++;
            }
            else{
                x *= 2;
                ans++;
            }
        }
        return ans;
    }
};

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值