[贪心法+回溯法]leetcode322:零钱兑换(medium)

题目:
[贪心法+回溯法]leetcode322:零钱兑换(medium)_第1张图片
题解:

  • 贪心+回溯
  • 贪心:将零钱由大到小排序,便于首先选择面值较大的零钱。
  • 回溯:若某个零钱选择之后,它后面的小零钱不能完成兑换的话,我们需要回溯,也就是将面值较大的零钱减少一张。
  • 加速 or 剪枝:每次直接将面值大的零钱选用最大张数,加速零钱兑换;若可兑换的零钱数大于 res 了,那么我们应该剪枝,也就是将将面值较大的零钱减少一张。

代码如下:

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        if(!amount)return 0;
        int res=INT_MAX;
        sort(coins.rbegin(),coins.rend());//由大到小排序,便于贪心地选取面值大的零钱
        dfs(coins,amount,0,0,res);
        return res==INT_MAX?-1:res;
    }

    //回溯寻找满足情况的最少零钱数,k表示一次可拿coins[i]的最大次数,若后面不能达到零钱完全兑换或者兑换的零钱数大于res时,用来回溯k--或剪枝
    //index用来遍历coins,count用来统计已用的零钱数
    void dfs(vector<int>& coins,int amount,int count,int index,int& res){
        if(amount==0){res=min(res,count);return;}
        if(index==coins.size())return;
        for(int k=amount/coins[index];k>=0&&k+count<res;--k){//k用来枚举所有零钱兑换的状态的
            dfs(coins,amount-k*coins[index],count+k,index+1,res);
        }
    }
};

你可能感兴趣的:(#,贪心,#,回溯,leetcode刷题)