279.完全平方数

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

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

:痕迹

java 复制代码
class Solution {
    public int numSquares(int n) {
        // 从nums(完全平方数构成的数组)选和为n的组合
        // 1、4、9、16、25、36、49、64...
        int sqrt = (int)Math.sqrt(n);
        int[] nums = new int[sqrt];
        for(int i = 0; i < nums.length; i++){
            nums[i] = (i + 1) * (i + 1);
        }
        // 容量n
        // dp代表数量,
        // dp[j]的值是如何保证,当容量为j的时候,找到【数量最少】的【和为j】的
        int[] dp = new int[n + 1];
        int max = Integer.MAX_VALUE;
        for(int i = 1; i <= n; i++) dp[i] = max;
        /*
        for(int i = 1; i <= n; i++){
            for(int j = 0; j < nums.length; j++){
                // 每次就决定加 / 不加 这个数。而这个数不是连续递增的,1.4.9.16.25.
                // 那就说明,必定有一些数,不能由nums中的数相加的来(不是的,nums中还有1,所以必定能表示所有数字)
                
                // 加不了当前的数
                if(i < nums[j]) dp[i] = dp[i - 1];
                // 加上当前这个nums[j],则数量dp +1
                else dp[i] = Math.min(dp[i], dp[i - nums[j]] + 1);
            }
        }
        */
        // dp[0] = 1;
        for(int i = 0; i < nums.length; i++){
            for(int j = nums[i]; j <= n; j++){
                if(j == nums[i]) dp[j] = 1;
                else dp[j] = Math.min(dp[j], dp[j - nums[i]] + 1);
            }
        }
        return dp[n];
    }
}

感想:dp不知道先遍历容量还是数组的话,就都尝试一下。

|----|-----|-----|-----|
| | i=0 | i=1 | i=2 |
| 0 | 0 | 0 | 0 |
| 1 | 1 | | |
| 2 | 2 | | |
| 3 | 3 | | |
| 4 | 4 | 1 | |
| 5 | 5 | 2 | |
| 6 | 6 | 3 | |
| 7 | 7 | 4 | |
| 8 | 8 | 2 | |
| 9 | 9 | 3 | 1 |
| 10 | 10 | 4 | 2 |
| 11 | 11 | 5 | 3 |
| 12 | 12 | 3 | 4 |

每个容量(上图中的行数据)取后面的最小值。对应代码:dpj = Math.min(dpj, dpj - nums\[i] + 1);

:默写加深印象

java 复制代码
public int numSquares(int n){
    // 需要自己构造数组
    int sqrt = (int)Math.sqrt(n);
    int[] nums = new int[sqrt];
    for(int i = 0; i < sqrt; i++) nums[i] = (i + 1) * (i + 1);
    // 
    int[] dp = new int[n + 1];
    int max = Integer.MAX_VALUE;
    for(int i = 1; i <= n; i++) dp[i] = max;
    for(int i = 0; i < nums.length; i++){
        for(int j = nums[i]; j <= n; j++){
            if(j == nums[i]) dp[j] = 1;
            else dp[j] = Math.min(dp[j], dp[j - nums[i]] + 1);
        }
    }
    return dp[n];
}

:改进

java 复制代码
public int numSquares(int n){
    // 需要自己构造数组
    int sqrt = (int)Math.sqrt(n);
    int[] nums = new int[sqrt];
    for(int i = 0; i < sqrt; i++) nums[i] = (i + 1) * (i + 1);
    // 
    int[] dp = new int[n + 1];
    int max = Integer.MAX_VALUE;
    // 这里要么从1开始遍历,要么从0开始,但还要把dp[0] = 0初始化。
    for(int i = 1; i <= n; i++) dp[i] = max;
    for(int i = 0; i < nums.length; i++){
        for(int j = nums[i]; j <= n; j++){
            dp[j] = Math.min(dp[j], dp[j - nums[i]] + 1);
        }
    }
    return dp[n];
}
相关推荐
hetao17338374 小时前
2026-10-03~04 hetao1733837 的刷题记录
c++·算法
Zootopia6265 小时前
飞行力学知识梳理1|飞行性能与稳定性
人工智能·python·算法·机器学习·无人机·学习方法·信息与通信
longlongzihan5 小时前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
2601_960356386 小时前
2027校招采购岗解析:数学基础如何迁移到需求预测、成本与供应商分析
人工智能·算法
h_a_o777oah7 小时前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分
HEJOO97 小时前
指针的算术运算详解
java·数据结构·算法
Coder-magician7 小时前
《代码随想录》刷题打卡day47:并查集-part01
数据结构·算法·图论
垆边人似月.7 小时前
VLAN 资源池(100~200 分档)
数据结构·算法
潼心1412o8 小时前
C++初阶(长期更新)第6讲:类和对象(下)
开发语言·c++·算法
星光开发者8 小时前
基于决策树随机森林算法的小说推荐系统的设计与实现-计算机毕设【课程设计】78485
vue.js·算法·微信小程序·django·php·课程设计·express