【动态规划】完全平方数

【动态规划】leetcode T279 完全平方数

题目描述

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

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。
例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

示例 :

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

这道题和硬币问题很相似,是一道典型的动态问题。

题目类型

当遇到下列问题,且问题可以分解成子问题来解决,考虑用动态规划来解决。

  1. 最大值最小值
  2. 可不可行
  3. 方案总数

解题思路

解动态规划题,最重要的是列出动态转移方程。考虑子问题,如果和为 0 ~ i -1(0,1,2,…,i,i-1)完全平方数的最少数量存于dp中,那么对于当前数字 i,dp[ i ] = min(dp[ i ] , dp[ i - j * j ] + 1 ),对所有 i - j*j >= 0, dp[i] 最多可以由i个1组成,初始化dp[i] = 1

例如,dp[5] = min(dp[5]=5,dp[5-1]+1,dp[5-4]+1)

具体步骤

  1. 首先初始化长度为 n+1 的数组 dp,每个位置都为 0,如果 n 为 0,则结果为 0
    在这里插入图片描述

  2. 对数组进行遍历,下标为 i,每次都将当前数字先更新为最大的结果,即 dp[i]=i, i = 1时,要求 i - j * j >= 0, j 只能取1
    dp[1] = 1
    dp[i - j* j] + 1 = dp[1-1*1] + 1 = dp[0] + 1 = 1
    因此dp[1] = 1
    在这里插入图片描述
    在这里插入图片描述

  3. 下一步 i = 2,初始化dp[2] = 2, 要求 i - j * j >= 0, j 也是只能取1
    dp[2] = 2
    dp[i - j* j] + 1= dp[2 - 1*1] + 1= dp[1] + 1 = 1+1 = 2
    所以最后dp[2] = 2

动态转移方程为:dp[i] = MIN(dp[i], dp[i - j * j] + 1),i 表示当前数字,j*j 表示平方数时间复杂度:O(n*sqrt(n))O(n∗sqrt(n)),sqrt 为平方根
在这里插入图片描述

  1. 下一步 i = 3,初始化dp[2] = 3, 要求 i - j * j >= 0, j 也是只能取1,
    dp[3] = 3
    dp[i - j* j] + 1= dp[3 - 1*1] + 1= dp[2] + 1= 2+1 = 3
    所以最后dp[3] = 3
    在这里插入图片描述
    在这里插入图片描述

  2. 下一步 i = 4,初始化dp[2] = 3, 要求 i - j * j >= 0, j 能取1,2
    j = 1,
    dp[3] = 3
    dp[i - j * j ] + 1 = dp[ 3-11] + 1= dp[2] + 1= 3
    此时,dp[4] 更新为 3
    在这里插入图片描述
    j = 2
    dp[4] = 3
    dp[i - j * j ] + 1 = dp[ 4-2
    2] + 1= dp[0] + 1= 1
    因此 dp[4] = 1
    在这里插入图片描述
    在这里插入图片描述

  3. i = 5, 同理,j = {1,2}
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

代码

class Solution:
    def numSquares(self, n: int) -> int:
		dp = [0]*(n+1)
		
		for i in range(1,n+1):
		    dp[i] = i
		    for j in [k for k in range(1,i) if k*k <= i]:
		        dp[i] = min(dp[i],dp[i-j*j]+1)    
		return dp[-1]
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值