Leetcode279.完全平方数

279. 完全平方数

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,14916 都是完全平方数,而 311 不是。

示例 1:

1
2
3
>输入:n = 12
>输出:3
>解释:12 = 4 + 4 + 4

示例 2:

1
2
3
>输入:n = 13
>输出:2
>解释:13 = 4 + 9

提示:

  • 1 <= n <= 104

把题目翻译一下:完全平方数就是物品(可以无限件使用),凑个正整数n就是背包,问凑满这个背包最少有多少物品?

动规五部曲分析如下:

1.确定dp数组(dp table)以及下标的含义
dp[j]:和为j的完全平方数的最少数量为dp[j]

2.确定递推公式
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]);

3.dp数组如何初始化
dp[0]表示 和为0的完全平方数的最小数量,那么dp[0]一定是0。

4.确定遍历顺序
我们知道这是完全背包,

如果求组合数就是外层for循环遍历物品,内层for遍历背包。

如果求排列数就是外层for遍历背包,内层for循环遍历物品。

image-20240902135028480

最终代码:

1
2
3
4
5
6
7
8
9
10
11
12
class Solution(object):
def numSquares(self, n):
nums = set([i * i for i in range(1, int(n**0.5)+1)])
dp = [10**4]*(n + 1)
dp[0] = 0
# 遍历背包
for j in range(1, n + 1):
# 遍历物品
for num in nums:
if j >= num:
dp[j] = min(dp[j], dp[j - num] + 1)
return dp[n]