题目:
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
思路:
本质:背包问题
需要提前求出需用到的平方数,不然会超时
解答:
方法一:
class Solution:
def numSquares(self, n: int) -> int:
#dp[i]:都使用完全平方数1时,所需使用的完全平方数量最多
dp=[i for i in range(n+1)]
#预处理出所有可能用到的完全平方数
squares=[i**2 for i in range(1,int(n**0.5)+1)]
for square in squares:
for i in range(square,n+1):
dp[i]=min(dp[i],dp[i-square]+1)
return dp[n]
方法二:完全背包
物品:完全平方数(可无限次使用)
背包:容量为n
求:装满背包所需使用的物品的最少数目。
(1)先遍历背包,再遍历物品
class Solution:
def numSquares(self, n: int) -> int:
#dp[i]:和为i所需要的完全平方数的最少数量
dp=[float('inf')]*(n+1)
dp[0]=0
#先遍历背包,再遍历物品
for j in range(1,n+1):
i=1
while i*i<=j:
dp[j]=min(dp[j],dp[j-i*i]+1)
i+=1
return dp[n]
另外一种写法:
class Solution:
def numSquares(self, n: int) -> int:
#dp[i]:和为i所需要的完全平方数的最少数量
dp=[float('inf')]*(n+1)
dp[0]=0
#先遍历背包,再遍历物品
for j in range(1,n+1):
for i in range(1,j+1):
if i*i>j:
break
else:
dp[j]=min(dp[j],dp[j-i*i]+1)
return dp[n]
换一种初始化方式:
class Solution:
def numSquares(self, n: int) -> int:
#dp[i]:和为i所需要的完全平方数的最少数量,当完全平方数均使用1时数量最多
dp=[i for i in range(n+1)]
#先遍历背包,再遍历物品
for j in range(1,n+1):
for i in range(1,j+1):
if i*i>j:
break
else:
dp[j]=min(dp[j],dp[j-i*i]+1)
return dp[n]
(2) 先遍历物品,再遍历背包
class Solution:
def numSquares(self, n: int) -> int:
#dp[i]:和为i所需要的完全平方数的最少数量
dp=[float('inf')]*(n+1)
dp[0]=0
#先遍历物品,再遍历背包
for i in range(1,n+1):
if i*i>n:
break
for j in range(i*i,n+1):
dp[j]=min(dp[j],dp[j-i*i]+1)
return dp[n]