322.零钱兑换

322.零钱兑换

题目:https://leetcode.cn/problems/coin-change

思路

经典的多重背包问题,只要把其中一处 i-1 改为 i 即可

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size();
        auto dfs = [&](this auto&& dfs, int i, int c) -> int {

            if (i < 0) {
                return c == 0 ? 0 : INT_MAX / 2;
            }

            if (c < coins[i]) {
                return dfs(i - 1, c);
            }
            return min(dfs(i - 1, c), dfs(i, c - coins[i]) + 1);
        };
        int res = dfs(n - 1, amount);
        return res == INT_MAX / 2 ? -1 : res;
    }
};

回溯加记忆化搜索

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size();
        vector memo(n, vector<int>(amount + 1, -1));

        auto dfs = [&](this auto&& dfs, int i, int c) -> int {

            if (i < 0) {
                return c == 0 ? 0 : INT_MAX / 2;
            }

            int& res = memo[i][c];
            if (res != -1) {
                return res;
            }

            if (c < coins[i]) {
                return res = dfs(i - 1, c);
            }
            return res = min(dfs(i - 1, c), dfs(i, c - coins[i]) + 1);
        };
        int res = dfs(n - 1, amount);
        return res == INT_MAX / 2 ? -1 : res;
    }
};

回溯改递推

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size();
        vector f(n + 1, vector<int>(amount + 1, INT_MAX / 2));
        f[0][0] = 0;

        for (int i = 0; i < n; i++) {
            for (int c = 0; c <= amount; c++) {
                if (c < coins[i]) {
                    f[i + 1][c] = f[i][c];
                } else {
                    f[i + 1][c] = min(f[i][c], f[i + 1][c - coins[i]] + 1);
                }
            }
        }
        int res = f[n][amount];
        return res == INT_MAX / 2 ? -1 : res;
    }
};

改为滚动数组

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size();
        vector f(2, vector<int>(amount + 1, INT_MAX / 2));
        f[0][0] = 0;

        for (int i = 0; i < n; i++) {
            for (int c = 0; c <= amount; c++) {
                if (c < coins[i]) {
                    f[(i + 1) % 2][c] = f[i % 2][c];
                } else {
                    f[(i + 1) % 2][c] = min(f[i % 2][c], f[(i + 1) % 2][c - coins[i]] + 1);
                }
            }
        }
        int res = f[n % 2][amount];
        return res == INT_MAX / 2 ? -1 : res;
    }
};