【LeetCode每日一题】零钱兑换

92 篇文章 0 订阅
85 篇文章 0 订阅

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

示例 1:

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

输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。

来源:力扣(LeetCode)

搜索

对于这个题目,首先想到了暴力解决…使用逐个尝试的方法,遍历所有的可能,最后通过对比找出所需硬币数最小的一种情况。但是肯定超时。

class Solution {
    int coinChange2(int index, vector<int>& coins, int amount) {
        if (amount == 0) return 0;
        if (index< coins.size() && amount > 0) {
            int max_num= amount / coins[index];
            int min_num = INT_MAX;
            for (int x = 0; x <= max_num; x++) {
                if (amount >= x * coins[index]) {
                    int res = coinChange2(index+ 1, coins, amount - x * coins[index]);
                    if (res != -1) min_num = min(min_num, res + x);
                }
            }
            return min_num == INT_MAX ? -1: min_num;
        }
        return -1;
    }
public:
    int coinChange(vector<int>& coins, int amount) {
        return coinChange2(0, coins, amount);
    }
};

自下而上的动态规划

F ( i ) = m i n j = 0 , . . . n − 1 ( F ( i − c j ) + 1 ) F(i) = min_{j=0,...n-1}(F(i-c_j) + 1) F(i)=minj=0,...n1(F(icj)+1)

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int max = amount+1;
        vector<int> v(max,max); // 定义一个数组,amount+1长度,每个元素初始值都为max
        v[0]= 0;
        for(int i=0;i<=amount;i++){
        	for(int j=0;j<coins.size();j++){
        		if(i-coins[j]>=0){
        			v[i] = min(v[i], v[i-coins[j]]+1);
        		}
        	}
        }
        // 因为初始为amount+1,若大于amount,说明没凑够
        return v[amount]>amount?-1:v[amount];
    }
};

自上而下

F ( i ) = m i n i = 0 , . . . , n − 1 F ( i − c i ) + 1 F(i) = min_{i=0,...,n-1}F(i-c_i) + 1 F(i)=mini=0,...,n1F(ici)+1

public class Solution {

  public int coinChange(int[] coins, int amount) {
    if (amount < 1) return 0;
    return coinChange(coins, amount, new int[amount]);
  }

  private int coinChange(int[] coins, int rem, int[] count) {
    if (rem < 0) return -1;
    if (rem == 0) return 0;
    if (count[rem - 1] != 0) return count[rem - 1];
    int min = Integer.MAX_VALUE;
    for (int coin : coins) {
      int res = coinChange(coins, rem - coin, count);
      if (res >= 0 && res < min)
        min = 1 + res;
    }
    count[rem - 1] = (min == Integer.MAX_VALUE) ? -1 : min;
    return count[rem - 1];
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值