【动态规划:背包问题】完全平方数

文章目录

279. 完全平方数

279. 完全平方数

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

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

示例 1:

复制代码
输入:n = 12
输出:3 
解释:12 = 4 + 4 + 4

示例 2:

复制代码
输入:n = 13
输出:2
解释:13 = 4 + 9

提示:

  • 1 <= n <= 104

解题思路

状态表示

​ 根据 "经验 + 状态表示",可得 dp[i][j] 表示在前 i 个完全平方数中选,总和正好等于 j,此时的完全平方数的最少数量!

状态转移方程

​ 状态转移方程大体上还是一样的,只不过细节稍微变了点:

初始化

​ 第一列还是一样不需要初始化,放到填表的时候一起去填!

​ 第一行除了第一个元素之外 ,其它元素其实是不满足状态的,那么为了求最小值的时候不要干扰,我们将其 初始化为 0x3f3f3f3f。

遍历顺序

​ 从上往下,从左往右遍历。

返回值

​ 根据状态表示,我们只需要 返回 dp[m][n] 即可,其中 m 表示根号 n ,因为我们只需要 i 遍历到根号 n 即可,再大了的话其完全平方数就超过 n 了,没意义了!

cpp 复制代码
class Solution {
public:
    int numSquares(int n) {
        // 创建dp表,dp[i][j] 表示在前i个完全平方数中选,总和正好等于j,此时完全平方数的最少数量
        // 并且因为i一定不会走到n那里,因为i*i <= n,所以只需要走到根号n即可
        int m = sqrt(n);
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));

        // 初始化
        for(int j = 1; j <= n; ++j)
            dp[0][j] = 0x3f3f3f3f;

        for(int i = 1; i <= m; ++i)
        {
            for(int j = 1; j <= n; ++j)
            {
                dp[i][j] = dp[i - 1][j];
                if(j >= i*i)
                    dp[i][j] = min(dp[i][j], dp[i][j - i*i] + 1);
            }
        }
        return dp[m][n];
    }
};

优化

所有的「背包问题」,都可以进行空间上的优化。

对于 完全背包 类型的,我们的优化策略是:

  • 删掉第一维
cpp 复制代码
class Solution {
public:
    int numSquares(int n) {
        int m = sqrt(n);
        vector<int> dp(n + 1, 0x3f3f3f3f);

        // 初始化
        dp[0] = 0;

        for(int i = 1; i <= m; ++i)
            for(int j = i*i; j <= n; ++j)
                dp[j] = min(dp[j], dp[j - i*i] + 1);

        return dp[n];
    }
};
相关推荐
言乐65 分钟前
Python区分广度优先深度优先宽度优先的区别
python·算法·深度优先·广度优先·宽度优先
Rnan-prince18 分钟前
LeetCode 股票买卖系列:一个动态规划状态机模板通吃四题
leetcode·动态规划
如意猴23 分钟前
【C++】007 C/C++ 内存管理机制、malloc与new的区别及模板初阶
java·c++·算法
朝朝辞暮i26 分钟前
C++ 第 32 课:main()、rclcpp::init()、spin()、shutdown()
开发语言·c++·算法
汉克老师31 分钟前
GESP2026年9月认证C++一级( 第三部分编程题(1、新龟兔赛跑))精讲
c++·gesp·小学生·学c++编程
沫璃染墨1 小时前
《从零入门Linux系统篇(五十七):线程篇·十——生产者消费者模型进阶:从环形缓冲区到POSIX信号量》
linux·运维·服务器·开发语言·c++·系统架构·信号处理
wuminyu1 小时前
LockStack在虚拟线程Mount和Unmount拷贝过程剖析
java·linux·c语言·jvm·c++
知识分享小能手2 小时前
C++ 学习教程,从入门到精通,string类和标准模板库 — 完整知识点详解(16)
开发语言·c++·学习
无忧.芙桃2 小时前
位图妙用:512MB 实现 40 亿整数的存在性查询
c语言·c++·面试·哈希算法
ShineWinsu2 小时前
对于Redis:Steam、Geospatial、Hyperloglog、Bitmap、Bitfield类型的解析
数据库·c++·redis·分布式·缓存·面试·zset