322. 零钱兑换 279.完全平方数

322. 零钱兑换 

题目:

给一个不同数额硬币的数组和一个目标金额,硬币可取无限次,求用硬币达到总金额的最小硬币数量。(求不同组合数/排列数,但是硬币数量最小)

思路:

求硬币数量最小,与组合数/排列数无关,所以遍历顺序,正序倒序均可。

dp[j]含义:
dp[j]:凑成总金额j的最小硬币数量为dp[j]

递推公式:
目标金额为j-coin[i]的最小硬币数量为dp[j-coin[i]],所以dp[j] = dp[j-coin[i]]+1。考虑加不加1

(硬币数量,无论无论多大,数量都是1)

初始化:
dp[0]=0,目标金额为0,那么对应的最少硬币总数为0,因为有+1存在,所以不影响初始化启动

遍历顺序:

与组合数/排列数无关,倒序正序均可,这里正序,先物品(硬币)后背包(目标金额)。

总代码:

class Solution {
public:
    int coinChange(vector& coins, int amount) {
        vector 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;//总额不超过力扣上线INT_MAX
        return dp[amount];
    }
};

279.完全平方数

题目:

给一个不同完全平方的数组和一个目标总和,不同完全平方数可取无限次,求用完全平方数达到目标总和的最小完全平方的数量。(求不同组合数/排列数,但是所用完全平方的数量最小)

完全平方数:是另一个正整数的平方,比如1,4,9是。11,3,0不是。

思路:

求达到目标总和的数量最小,与组合数/排列数无关,所以遍历顺序,正序倒序均可。与上面一道题一模一样的..

dp[j]含义:

dp[j]:达到目标总和j的最小完全平方数的数量为dp[j]

递推公式:

dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。

此时我们要选择最小的dp[j],所以递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]);

初始化:

dp[0]=0,虽然0可以解释为0*0,有一种,但是,从递推公式可以看出

dp[j] = min(dp[j - i * i] + 1, dp[j]);是一直在选最小值的,如果dp[0]等于0,那后续值都会被0覆盖,而0则因为完全平方数里有 1 的存在(可以凑成任意总和,不可能拼凑数是0),所以为了这个目的,dp[0]=0

遍历顺序:

与组合数/排列数无关,倒序正序均可,这里正序,先物品(完全平方数)后背包(目标总和)。

总代码:

// 版本一
class Solution {
public:
    int numSquares(int n) {
        vector dp(n + 1, INT_MAX);
        dp[0] = 0;
        for (int i = 0; i <= n; i++) { // 遍历背包
            for (int j = 1; j * j <= i; j++) { // 遍历物品
                dp[i] = min(dp[i - j * j] + 1, dp[i]);
            }
        }
        return dp[n];
    }
};

你可能感兴趣的:(算法)