279. 完全平方数

在这里插入图片描述
i-jj就是x
https://leetcode-cn.com/problems/perfect-squares/solution/chao-zhi-bai-kao-zui-jiang-xiao-xue-sheng-du-neng-/
又是dp,最少(最多)=最优解就要想到dp。
此处dp[i]可能由dp[0]到dp[i-1]推出,因为i一定等于x+j
j,那么dp[i]就是dp[x]+1,开一个大小为n+1的dp数组(为啥n+1自己想),dp[0]就等于0,从1遍历到n,在里面找i的最优解,j从1开始遍历,退出条件是i-jj<0,那么dp[i]就等于dp[i]和dp[i-jj]+1中比较小的那个。所以我们一开始要将dp数组赋为无穷大

class Solution {
public:
    int numSquares(int n) {
        // 1,对于正整数N, 所有的解都是 N = 一个整数的平方 + 另一个整数; 直白点, N = AxA + B
        // 2, 而B又是由 "一个整数的平方 + 另一个整数" 组成的; 那么, B = CxC + D
        // 3,总结下就是:N = IxI + N' 而 N' = IxI + N''
        //dp[i]存的是组成数字i需要几个完全平方数,dp[i]就等于dp[x]+1
        //x就是0到i-1中,x+?*?=i,?*?是一个平方数,证明x到i只需要加上一个完全平方数即可
        //dp[x]又要是dp[1]到dp[i-1]最小的
        //dp[13] = dp[4]+1
        //dp[12] = dp[8]+1
        vector<int> dp(n+1,INT_MAX);
        dp[0] = 0;
        for(int i = 1; i <= n; ++i){
            //j就是上面说的?,i-j*j就是上面的x
            //dp[4],j=1,证明x是3,dp[3]等于3
            //dp[4],j=2,证明x是0,dp[0]等于0
            for(int j = 1; i - j * j >= 0; ++j){
                dp[i] = min(dp[i],dp[i-j*j]+1);
            }
        }
        return dp[n];
    }
};
class Solution {
public:
    //参数有n,nums也就是用的数字的数量,index,当前用到的完全平方数是几,接下来用的只能小于等于当前这个
    // void dfs(int n, int nums, int index){
    //     if(n == 0){
    //         res = min(nums,res);
    //         return;
    //     }
    //     else if(nums < 0) return;
    //     for(int i = index; i >= 1; --i){
    //         dfs(n-i*i,nums+1,i);
    //     }
    // }
    int numSquares(int n) {
        //个数最少,那么用的完全平方数就要尽可能的大
        //感觉有点dp的味道,不是dp就是dfs爆搜,把所有情况搜出来,比较用的元素最少的
        //爆搜要超时,dp或者记忆化
        // for(int i = (int)sqrt(n); i >= 1; --i){
        //     dfs(n-i*i,1,i);
        // }
        // return res;

        vector<int> dp(n+1,INT_MAX);
        //从前往后填表
        dp[0]=0;//初始化dp数组最重要!
        for(int i = 1; i <= n; ++i){
            //比如dp[12]就可以推出dp[8]+1或者dp[11]+1,12和8和11中间差了就是一个完全平方数,所以只要推出前面的,就能计算出dp[12]的结果,因为就几种情况,dp[11]+1,dp[8]+1,dp[3]+1
            for(int j = 1; i -j*j >= 0; ++j){
                dp[i] = min(dp[i],dp[i-j*j]+1);
            }
        }
        return dp[n];
    }
// private:
//     int res = INT_MAX;
};

三刷了,这次真的轻松做出了。dp[i]的含义是最少可以用dp[i]个完全平方数加起来等于i

class Solution {
public:
    int numSquares(int n) {
        //dp的题,dp[i]的含义是可以用dp[i]个完全平方数加起来等于i
        //所以状态转移方程是dp[i] = min(dp[i],dp[i-j*j]+1)
        //从小到大进行填表,初始化为dp[0]=0
        vector<int> dp(n+1,INT_MAX);
        dp[0] = 0;
        for(int i = 1; i <= n; ++i){
            for(int j = 1; i - j*j >= 0; ++j){
                dp[i] = min(dp[i],dp[i-j*j]+1);
            }
        }
        return dp[n];
    }
};

四刷

class Solution {
public:
    int numSquares(int n) {
        //dp[i]记录的是组成i最少需要几个完全平方数
        //dp[i] = min(dp[i-j*j]+1,dp[i]),因为i一定可以从j*j到i,i-j*j可以通过dp[i-j*j]个数字组成,j*j又一定是一个完全平方数
        //初始化:dp[0]=0,当组成0的时候需要0个完全平方数即可
        vector<int> dp(n+1,INT_MAX);
        dp[0] = 0;
        for(int i = 1; i <= n ;++i){
            //所以一直从j=1遍历到i-j*j<0为止,等于0也要包括进去
            for(int j = 1; i-j*j>=0; ++j){
                dp[i] = min(dp[i-j*j]+1,dp[i]);
            }
        }
        return dp[n];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值