回溯法——20191231

5 Leetcode 322.零钱兑换
5.1 题目描述
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

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

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

说明:
你可以认为每种硬币的数量是无限的。
5.2 分析
使用回溯法,由于是最小的,因此回溯到所有可以组成的情况,找出其中的最小值。
5.3 代码
int compare(const void* a, const void* b) {
return (int)a - (int)b;
}

int min(int a, int b) {
return a < b ? a : b;
}

//回溯法,从可以组成的里面选出最小的
void canChange(int* coins, int index, int amount, int cnt, int* minCnt) {
if(index < 0 || amount < 0 || (cnt + amount / coins[index]) >= *minCnt) { //剪枝
return;
}

if(amount % coins[index] == 0) {
    *minCnt = min(*minCnt, cnt + amount / coins[index]); //寻找更小的值
    return;
}

int i = 0;
for(i = amount / coins[index]; i >= 0; i--) {
    canChange(coins, index - 1, amount - i * coins[index], cnt + i, minCnt);
}

}

int coinChange(int* coins, int coinsSize, int amount) {
if(coinsSize <= 0 || amount < 0) {
return -1;
}
if(amount == 0) {
return 0;
}
qsort(coins, coinsSize, sizeof(int), compare);

int* minCnt = (int*)malloc(sizeof(int));
if(minCnt == NULL) {
    return -1;
}
*minCnt = INT_MAX;

int result = -1;
canChange(coins, coinsSize - 1, amount, 0, minCnt);
result = *minCnt;

free(minCnt);
minCnt = NULL;
return result == INT_MAX ? -1 : result;

}

发布了39 篇原创文章 · 获赞 1 · 访问量 856

猜你喜欢

转载自blog.csdn.net/weixin_42268479/article/details/103785886