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]小,那么要更新:
因为零钱兑换一定不是排列而是组合,所以我们应该先遍历物品,内部遍历背包容量。
可是初始状态呢?
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
找到从之间所有的完全平方数作为我们的物品列表。
然后做完全背包。
和为 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]