leetcode刷题(48)——279.完全平方数

一、题目

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

示例 1:

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

示例 2:

输入: n = 13
输出: 2
解释: 13 = 4 + 9.

二、思路——动态规划

完全平方数有 1,4,9,16 … … 我们的总体思路是:对于一个给定的正整数 n,我们首先找到组成和的完全平方数的所有组合,然后从中找到个数最少的即可。

  • 问题拆解:
    问题拆解就是要找到原问题与子问题之间的联系。对于任意 k(1 <= k <= n),组成 k 的完全平方数个数最多的情况就是 dp[k] = k,比如 dp[5] = 5,5 = 1+1+1+1+1。然后每次减去一个完全平方数,看能否将个数减少,比如组成 5 的完全平方数的组合还可以是 dp[5 - 1 * 1] + 1 = dp[4] + 1,或者 dp[5 - 2 * 2] + 1 = dp[1] + 1。那么对于任意 k,组成和的完全平方数的个数最少的组合,即为
    d p [ k ] = M a t h . m i n ( d p [ k ] , d p [ k − j × j ] + 1 ) dp[k] = Math.min(dp[k], dp[k - j \times j] +1) dp[k]=Math.min(dp[k],dp[kj×j]+1) 其中 j = 1,2,3 … …, j × j j \times j j×j 表示平方数,当然还要保证 k − j × j ≥ 0 k - j \times j \geq 0 kj×j0
    这样就找到了第 k k k 个问题和第 k − j × j k - j \times j kj×j 个子问题的联系。
  • 定义状态:
    根据上面的分析,将状态定义为:组成 k ( 1 ≤ k ≤ n ) k(1 \leq k \leq n) k(1kn) 的完全平方数个数最少的组合。
  • 推导状态转移方程:
    问题拆解中我们已经得到了状态转移方程:
    d p [ k ] = M a t h . m i n ( d p [ k ] , d p [ k − j × j ] + 1 ) dp[k] = Math.min(dp[k], dp[k - j \times j] +1) dp[k]=Math.min(dp[k],dp[kj×j]+1) 其中 j = 1,2,3 … …, j × j j \times j j×j 表示平方数,且 k − j × j ≥ 0 k - j \times j \geq 0 kj×j0
  • 寻找边界条件:
    当 n = 0 时,组合数为 0。所以在创建 dp 数组时多开一位,存放初始状态 dp[0] = 0。

三、代码

class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n + 1];
        for(int i = 1; i <= n; i++){
            dp[i] = i;
            for(int j = 1; i - j * j >= 0; j++){
               dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
            }
        }
        return dp[n];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值