LeetCode 322. 零钱兑换 + 518. 零钱兑换 II

99 阅读1分钟

322. 零钱兑换

class Solution {
public:
    int coinChange(vector<int>& coins, int m) {
        vector<int>f(m + 1, 1e8);//不用INT_MAX是容易+1后出界
        //f定义的是最少的硬币个数
        f[0]= 0;//
        for(auto v: coins) 
            for(int j = v; j <= m; j ++) {//完全背包问题,从小到大遍历
                f[j] = min(f[j], f[j - v] + 1);
            }
        if(f[m] == 1e8) return -1;
        return f[m];
    }
};
class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount + 1, INT_MAX);
        dp[0] = 0;
        for (int i = 0; i < coins.size(); i++) { // 遍历物品
            for (int j = coins[i]; j <= amount; j++) { // 遍历背包
                if (dp[j - coins[i]] != INT_MAX) { // 如果dp[j - coins[i]]是初始值则跳过
                    dp[j] = min(dp[j - coins[i]] + 1, dp[j]);
                }
            }
        }
        if (dp[amount] == INT_MAX) return -1;
        return dp[amount];
    }
};

518. 零钱兑换 II

class Solution {
public:
    int change(int amount, vector<int>& coins) {
        vector<int> f(amount + 1);// f(j) 表示硬币总面额为 j 时的方案数。
        f[0] = 1;//总面额为0是的方案书为1
        for(auto v : coins) {
            for(int j = v; j <= amount; j ++) //对于每一种硬币面额coins(i),j 从coins(i) 枚举到amount,累计转移 f(j)=f(j)+f(j−coins(i))。
最终答案为 f(amount)f(amount)。
                f[j] += f[j - v];
        }
        return f[amount];
    }
};
        //状态计算: 把最后一种硬币拿掉:f[i][j] = f[i-1][j-k*coins[i]], 这样的话时间复杂度是O(n^3)
        //优化: f[i][j] = f[i-1][j] + f[i-1][j-coins[i]] + f[i-1][j-2*coins[i]] + ...
        //       f[i][j-coins[i]] =  f[i-1][j-coins[i]] + f[i-1][j-2*coins[i]] + ...
        // f[i][j] = f[i-1][j] + f[i][j-coins[i]]
        // f[j] = f[j] + f[j-coins[i]]