279.完全平方数

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

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,14916 都是完全平方数,而 311 不是。

:痕迹

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 |

每个容量(上图中的行数据)取后面的最小值。对应代码:dp[j] = Math.min(dp[j], dp[j - 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];
}
相关推荐
智驱力人工智能4 分钟前
使用手机检测的智能视觉分析技术与应用 加油站使用手机 玩手机检测
深度学习·算法·目标检测·智能手机·视觉检测·边缘计算
姚瑞南24 分钟前
【AI 风向标】四种深度学习算法(CNN、RNN、GAN、RL)的通俗解释
人工智能·深度学习·算法
补三补四1 小时前
SMOTE 算法详解:解决不平衡数据问题的有效工具
人工智能·算法
RTC老炮1 小时前
webrtc弱网-RobustThroughputEstimator源码分析与算法原理
网络·算法·webrtc
努力努力再努力wz1 小时前
【C++进阶系列】:万字详解智能指针(附模拟实现的源码)
java·linux·c语言·开发语言·数据结构·c++·python
听风吹等浪起1 小时前
分类算法-逻辑回归
人工智能·算法·机器学习
敲代码的嘎仔1 小时前
JavaWeb零基础学习Day2——JS & Vue
java·开发语言·前端·javascript·数据结构·学习·算法
yacolex2 小时前
3.3_数据结构和算法复习-栈
数据结构·算法
茉莉玫瑰花茶2 小时前
动态规划 - 两个数组的 dp 问题
算法·动态规划
微笑尅乐2 小时前
从暴力到滑动窗口全解析——力扣8. 字符串转换整数 (atoi)
算法·leetcode·职场和发展