322. 零钱兑换(时间复杂度高)
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。你可以认为每种硬币的数量是无限的。
【错误解法】尝试贪心算法,但是逻辑有问题,如:10,4,3凑19,则10+4+4+4->10+4+4+3->10+4+4此时i==coins.size()从而退出循环返回-1,但实际上问题有解,10+3+3+3即可得到19。
测试点29/189。
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
sort(coins.begin(),coins.end());
reverse(coins.begin(),coins.end());
int sum=0;int i=0;int cnt=0;
//贪心算法 明显不可取如:10,4,3凑19
//则10+4+4+4->10+4+4+3->10+4+4此时i==coins.size()从而退出循环但实际上10+3+3+3即可得到19
while(i<coins.size()){//当前选择的硬币
while(sum<amount){//贪心算法
sum+=coins[i];
cnt++;
}
if(sum==amount)return cnt;
else{//此时sum>amount 则切换更小的硬币
sum-=coins[i];
i++;
}
}
return -1;
}
};
【错误解法】起初也尝试用此下回溯方法,先用大硬币,当第一次得到正确的组合时,则使用全局变量结束所有后续递归。但是逻辑有漏洞如10,7,1凑14返回的错误结果是cnt(10+1+1+1+1)=3但正确结果应该是cnt(7,7)=2。
class Solution {
public:
bool findFlag = false;
int cnt=0;
int finalCnt=0;
void backtracking(int startIndex, int &sum, int target, vector<int>& coins) {
if (sum == target) {
findFlag = true;
finalCnt=cnt;
return;
}
for (int i = startIndex; i < coins.size() && findFlag == false; i++) {
if (sum + coins[i] > target)
continue;
else {
sum += coins[i];
cnt++;
backtracking(i, sum, target, coins);
sum -= coins[i];
cnt--;
}
}
}
int coinChange(vector<int>& coins, int amount) {
sort(coins.begin(),coins.end());
reverse(coins.begin(),coins.end());
int sum=0;
backtracking(0,sum,amount,coins);
return finalCnt;
}
};
【超时但正确解法】尝试使用回溯法枚举所有sum==target的组合再记录最小的cnt,但是超时。而leetcode超时后面的测试点不会再运行,故仅通过了39/189的测试点
最后输入为:[411,412,413,414,415,416,417,418,419,420,421,422]用自己的VS运行可以得到正确结果24。
class Solution {
public:
bool findFlag = false;
int cnt=0;
int smallestCnt=10e6+11;
void backtracking(int startIndex, int &sum, int target, vector<int>& coins) {
if (sum == target) {
smallestCnt=min(smallestCnt,cnt);
return;
}
for (int i = startIndex; i < coins.size(); i++) {
if (sum + coins[i] > target)
continue;
else {
sum += coins[i];
cnt++;
backtracking(i, sum, target, coins);
sum -= coins[i];
cnt--;
}
}
}
int coinChange(vector<int>& coins, int amount) {
sort(coins.begin(),coins.end());
reverse(coins.begin(),coins.end());
int sum=0;
backtracking(0,sum,amount,coins);
if(smallestCnt==10e6+11)return -1;//说明该没找到任何一个组合
else return smallestCnt;
}
};

浙公网安备 33010602011771号