代码随想录第45天|322. 零钱兑换、279. 完全平方数

96 阅读2分钟

322. 零钱兑换

1. first idea

Our goal is to get the least number of coins to fill the amount.

So dp[j] denotes that the least number of coins[i] to fill the j.

如果当前dp[j - weight[i]] + 1比当前的dp[j]小,那么要更新:

dp[j]=min(dp[jweight[i]]+1,dp[j])dp[j] = min(dp[j - weight[i]] + 1, dp[j])

因为零钱兑换一定不是排列而是组合,所以我们应该先遍历物品,内部遍历背包容量。

可是初始状态呢?

2. doc reading

首先凑足总金额为0所需钱币的个数一定是0,那么dp[0] = 0;

其他下标对应的数值呢?

考虑到递推公式的特性,dp[j]必须初始化为一个最大的数,否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。

所以下标非0的元素都是应该是最大值。

dp = [float('inf')] * (amount + 1)  # 创建动态规划数组,初始值为正无穷大

可以参考一下最大值是怎么取的。

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        dp = [float('inf')] * (amount + 1)
        dp[0] = 0
        for obj_idx in range(len(coins)):
            for cap in range(1, amount + 1):
                if cap >= coins[obj_idx]:
                    dp[cap] = min(dp[cap], dp[cap - coins[obj_idx]] + 1)
        if dp[-1] == float('inf'):
            return -1
        return dp[-1]

279. 完全平方数

1. first idea

找到从[1,n][1, n]之间所有的完全平方数作为我们的物品列表。

然后做完全背包。

和为 n 的完全平方数的最少数量 所以导致做法和上一题差不多。

class Solution:
    def is_perfect_square(self, num):
        for i in range(1, num // 2 + 1):
            if (i * i) == num:
                return True
        return False

    def numSquares(self, n: int) -> int:
        nums = [1]
        for idx in range(1, n + 1):
            if self.is_perfect_square(idx): 
                nums.append(idx)
        dp = [float('inf')] * (n + 1)
        dp[0] = 0
        for idx in range(len(nums)):
            for cap in range(1, n + 1):
                if cap >= nums[idx]:
                    dp[cap] = min(dp[cap], dp[cap - nums[idx]] + 1)
        if dp[-1] == float('inf'):
            return -1
        return dp[-1]

n = 2752出现超时。

2. doc reading

将完全平方放进遍历物品循环里。

class Solution:
    def numSquares(self, n: int) -> int:
        dp = [float('inf')] * (n + 1)
        dp[0] = 0
        idx = 1
        while (idx * idx) <= n:
            sq_int = idx * idx
            for cap in range(1, n + 1):
                if cap >= sq_int:
                    dp[cap] = min(dp[cap], dp[cap - sq_int] + 1)
            idx += 1
        if dp[-1] == float('inf'):
            return -1
        return dp[-1]