文章最前: 我是Octopus,这个名字来源于我的中文名--章鱼;我热爱编程、热爱算法、热爱开源。所有源码在我的个人github ;这博客是记录我学习的点点滴滴,如果您对 Python、Java、AI、算法有兴趣,可以关注我的动态,一起学习,共同进步。
相关文章:
- LeetCode:55. Jump Game(跳远比赛)
- Leetcode:300. Longest Increasing Subsequence(最大增长序列)
- LeetCode:560. Subarray Sum Equals K(找出数组中连续子串和等于k)
文章目录:
源码github地址:https://github.com/zhangyu345293721/leetcode
题目描述:
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。
来源:力扣(LeetCode)
java实现方法1:
private int minCount=Integer.MAX_VALUE;
/**
* 硬币兑换
*
* @param coins 硬币兑换
* @param amount 数量
* @return 最小数量
*/
public int coinChange(int[] coins, int amount) {
Arrays.sort(coins);
searchHelper(coins, coins.length - 1, amount, 0);
return minCount == Integer.MAX_VALUE ? -1 : minCount;
}
/**
* 1、按金额从大到小,从多到少
* 2、预判低于最优解,终止递归
* 3、能整除即可返回
*
* @param coins 硬币数组
* @param index 下标
* @param amount 剩余没凑足的数量
* @param count 已经算的数量
*/
public void searchHelper(int[] coins, int index, int amount, int count) {
if (index < 0) {
return;
}
for (int c = amount / coins[index]; c >= 0; c--) {
int newCount = count + c;
if (amount - c * coins[index] == 0) {
minCount = Math.min(minCount, newCount);
break;//剪枝1
}
// 如果大于最小minCount就直接退出
if (newCount >= minCount) {
break; //剪枝2
}
searchHelper(coins, index - 1, amount - c * coins[index], newCount);
}
}
时间复杂度:O(n^2)
空间复杂度:O(n)
python实现方法1:
class Solution:
def helper(self, coins: List[int], count: int, index: int, amount: int, min_count: int):
'''
dfs帮助类
Args:
coins: 硬币数组
count: 数量
index: 下标
amount: 金额
min_count: 最小数
'''
if index >= len(coins):
return
n = amount // coins[index]
i = n
while i >= 0:
new_count = count + i
# 剪枝操作1
if amount == i * coins[index]:
min_count[0] = min(min_count[0], new_count)
break
# 剪枝操作2
if new_count >= min_count[0]:
break
self.helper(coins, new_count, index + 1, amount - i * coins[index], min_count)
i -= 1
def coin_change(self, coins: List[int], amount: int) -> int:
'''
兑换硬币最小数
Args:
coins: 硬币数组
amount: 金额大小
Returns:
最小数量
'''
min_count = [amount + 1]
coins.sort(reverse=True)
self.helper(coins, 0, 0, amount, min_count)
return -1 if min_count[0] == amount + 1 else min_count[0]
时间复杂度:O(n^2)
空间复杂度:O(n)
java实现方法2:
/**
* 动态规划
*/
public int coinChange(int[] coins, int amount) {
if( coins == null || coins.length < 1) {
return -1;
}
int [] dp = new int[amount + 1];
for(int i = 0; i <= amount; i++) {
dp[i] = 10001;
}
dp[0] = 0;
// 动态规划,找到最小值兑换个数
for(int i = 0; i < coins.length; i++) {
for(int j = 1; j <= amount; j++) {
int w = coins[i];
if( j >= w) {
dp[j] = Math.min(dp[j], dp[j - w] + 1);
}
}
}
return dp[amount] >= 10001 ? -1 : dp[amount];
}