力扣278 完全平方数(动态规划)

本文通过实例解析动态规划在求解组成一个数最少完全平方数个数问题的应用,详细介绍了算法思路及代码实现,加深了对动态规划的理解。通过初始化dp数组,动态转移方程不断寻找最优解,最终得出目标数所需的最少完全平方数个数。
摘要由CSDN通过智能技术生成

在这里插入图片描述

    以前总是不太知道什么题需要用到动态规划,这个题加深了我对动规的理解。先说说我刚开始的思路,我想的是找到比n小的最近的完全平方数,从它开始遍历,就拿12来说,先找到离她最近的完全平方数9,然后12-9=3,这个时候就需要再重新找比3最小的完全平方数,再进行这个循环,所以想要得到组成12最少的完全平方数的个数的时候,既要找组成9最少的完全平方的个数,然后找9的也需要找3的……所以就能推导出来,后面的最优解需要从前面的最优解得到,所以才要使用动规。

class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n + 1]; // 默认初始化值都为0
        for (int i = 1; i <= n; i++) {
            dp[i] = i; // 最坏的情况就是每次+1
            for (int j = 1; i - j * j >= 0; j++) { 
                dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
                 // 动态转移方程,j*j表示完全平方数
            }
        }
        return dp[n];
    }
}

    然后再来看看这个题的dp数组,dp[i]要初始化为i,因为组成一个数最坏的情况就是全都是1,然后dp[i]表示组成i需要的最少的完全平方数的个数。
dp[i] 可以由dp[i- j * j]推出, dp[i - j * j] + 1 便可以凑成dp[i]。
此时我们要选择最小的dp[j],所以递推公式:dp[j] = min(dp[j],dp[j - i * i] + 1);

以dp[4]为例,它可以分为1,dp[3],或者2,dp[0],所以dp[4]=min(dp[4],dp[4 -1 * 1]+1)
dp[4]=min(dp[4],dp[4-2 * 2]+1)

现在按照代码走一遍12,
    dp[1]初始化为1,dp[1]=min(dp[1],dp[1-1* 1 ]+1)中最小的,dp[1-11]+1=1,所以dp[1]=1;
    dp[2]初始化为2,然后进入循环,dp[2]=min(dp[2],dp[2-1 * 1]+1),dp[2-1 * 1]=dp[1]=1,然后再加个1,得到2,所以dp[2]=2,然后j++=2,2-2 * 2<0,所以不进循环了,最终dp[2]=2;
    dp[3]初始化为3,进入循环,dp[3]=min(dp[3],dp[3-1 * 1]+1),dp[3-1 * 1]=dp[2]=2,再加1,所以dp[3]=3,然后j++=2,3-2 * 2<0,不进循环,最终dp[3]=3
    dp[4]初始化为4,进入循环,dp[4]=min(dp[4],dp[4-1 * 1]+1),dp[4-1 * 1]=dp[3]=3,再加1,dp[4]=4,j++,4-2 * 2=0,进入循环,dp[4]=min(dp[4],dp[4-2 * 2]+1),dp[4-2
2]=dp[0],=0,再加一,dp[4]=1,然后就不进循环了,最后dp[4]=1;
    dp[5]初始化为5,进入循环,dp[5]=min(dp[5],dp[5-1 * 1]+1)
dp[5-1 * 1]=dp[4]=1,再加1,d[5]=2,然后再进入循环,dp[5]=min(dp[5],dp[5-2 * 2]+1),dp[5-2 * 2]=dp[1]=1,再加1,dp[5]=2;
    dp[6]初始化为6,dp[6]=min(dp[6],dp[6-1 * 1]+1),dp[6-1 * 1]=dp[5]=2,再加1,dp[6]=3,再进入循环,dp[6]=min(dp[6],dp[6-2 * 2]+1),dp[6-2 * 2]=dp[2]=2,再加1,所以d[6]=3
……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值