0718更新
class Solution:
def numSquares(self, n: int) -> int:
deq=[]#存储还剩余的残差值
visited=set()
deq.append((n,0))#一开始,什么都没做,当然是还剩余原数字(可以认为是n-0*0)
while deq != []:
#print(deq)
(head,nums) = deq.pop(0)#每次弹出一个残差
i = 1#对于每个残差,每次都尝试从1*1开始减
cur_res = head - i*i#新的残差值
while cur_res >= 0:#需保证没有减过头
if head - i*i == 0:#找到结果 此时应是最小轮数 即所需平方数的数量最少的
return nums + 1#返回此时的head对应轮次+1(即加上新的平方数对应的1)
if head - i*i not in visited:#如果还没找到结果,看看这个数之前是否找到过,这个是解决避免陷入至之前残差减过头也没有找到结果的重复计算。如果这个残差之前也没有找到结果,那么这个残差本次也找不到,因此不再计入deq
visited.add(head - i*i)
deq.append((head-i*i,nums+1))
i += 1
cur_res = head - i*i
思路:
使用自底向上的动态规划算法
对于完全平方数,如n=25, return 1即可
对于其它的数,首先找到比输入数字小的最大的平方数k
如,输入的n是12,则找到的是k=9
则,
dp[n] = min(dp[n-1] + 1,dp[n-4] + 1,dp[n-9] + 1,…,dp[n-k]+1)
class Solution:
def numSquares(self, n: int) -> int:
#先确定 比n小的最大的平方数
if n == 0 or n == 1:
return 1
small = 0
base = []
for i in range(n):
temp = i**2
if temp == n:
return 1
elif temp < n:
#small = i**2
base.append(temp)
elif i**2 > n:
break
dp = [0 for _ in range(n+1)]
dp[0] = 1
dp[1] = 1
for i in range(2,n+1):
dp[i] = n
if i in base:
dp[i] = 1
else:
for value in base:
if value <= i:
dp[i] = min(dp[i],dp[i-value] + 1 )
return dp[n]