322. 零钱兑换(时间复杂度高)

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;
    }
};
posted @ 2025-03-20 21:56  Cheauncey  阅读(125)  评论(0)    收藏  举报