LeetCode 热题 100_完全平方数(84_279_中等_C++)(动态规划(完全背包))

LeetCode 热题 100_完全平方数(84_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

题解:

解题思路:

思路一(动态规划(完全背包)):

1、题目要求一个整数 n,返回 和为 n 的完全平方数的最少数量。从样例一的解释中:12 = 4 + 4 + 4。我们发现4是可以重复使用的,这样就凑成一个整数,可重复使用自然而然的想到了完全背包。

2、具体思路如下:

① 首先考虑一个数 n 所包含的最大完全平方数是根号n=sqrt(n)。

② 可以将这个问题转化为完全背包问题:背包的容量为 n,物品的重量是 1 到 sqrt(n) 之间的完全平方数。

③ 使用一维dp数组,dpj 表示背包容量为 j 时,最少需要的物品数量(即最少的完全平方数个数)。

④ 状态转移方程:dpj = min(dpj, dpj - i × i + 1),等号右侧 dpj代表没放i×i,dpj - i × i + 1 代表放了 i×i 。

⑤ 初始化 dp0 = 0,因为容量为 0 时不需要任何物品。其余dp数组值为INT_MAX,因 dpj = min(dpj, dpj - i × i + 1) ,取两值中的最小值。
这个博主的背包问题讲解的不错

3、复杂度分析:

① 时间复杂度:O(n * sqrt(n)),其中 n 为给定的正整数。状态转移方程的时间复杂度为 O(sqrt(n)),共需要计算 n 个状态,因此总时间复杂度为 O(n * sqrt(n))。

② 空间复杂度:O(n)。dp 数组所需的空间。

代码实现

代码实现(思路一(动态规划(完全背包))):
cpp 复制代码
class Solution {
public:
    int numSquares(int n) {
        // 创建一个长度为 n+1 的 DP 数组,初始化为最大值 INT_MAX
        vector<int> dp(n+1, INT_MAX);
        
        // 背包容量为 0 时,所需物品数为 0
        dp[0] = 0;
        
        // 先遍历所有完全平方数 i * i
        for (int i = 1; i * i <= n; i++) {
            // 遍历背包容量 j,从 i*i 到 n,更新 dp[j] 的最小值  (只有j>=i*i 才能装下i*i)
            // 可重复使用遍历顺序是从左到右
            for (int j = i * i; j <= n; j++) {
                // 状态转移方程,选择当前完全平方数 i*i,更新 dp[j]
                dp[j] = min(dp[j], dp[j - i * i] + 1);
            }
        }
        
        // 返回最终的结果,即 n 需要的最少完全平方数个数
        return dp[n];
    }
};
以思路一为例进行调试
cpp 复制代码
#include<iostream>
#include<vector>
using namespace std;

class Solution {
public:
    int numSquares(int n) {
        // 创建一个长度为 n+1 的 DP 数组,初始化为最大值 INT_MAX
        vector<int> dp(n+1, INT_MAX);
        
        // 背包容量为 0 时,所需物品数为 0
        dp[0] = 0;
        
        // 先遍历所有完全平方数 i * i
        for (int i = 1; i * i <= n; i++) {
            // 遍历背包容量 j,从 i*i 到 n,更新 dp[j] 的最小值  (只有j>=i*i 才能装下i*i)
            for (int j = i * i; j <= n; j++) {
                // 状态转移方程,选择当前完全平方数 i*i,更新 dp[j]
                dp[j] = min(dp[j], dp[j - i * i] + 1);
            }
        }
        
        // 返回最终的结果,即 n 需要的最少完全平方数个数
        return dp[n];
    }
};

int main() {
    Solution s;
    // 输出 numSquares(13) 的结果,期望输出 2(13 = 4 + 9)
    cout << s.numSquares(13) << endl;
    return 0;
}

LeetCode 热题 100_完全平方数(84_279)原题链接

欢迎大家和我沟通交流(✿◠‿◠)

相关推荐
longlongzihan17 分钟前
LeetCode 5. 最长回文子串:从暴力匹配到中心扩展的思维演进
c++·算法·leetcode
苦瓜打怪兽25 分钟前
leetcode 热题100(11. 盛最多水的容器)
python·算法·leetcode
多弗朗皮卡丘28 分钟前
C++继承
c++·继承
汉克老师1 小时前
GESP2026年9月认证C++七级( 第三部分编程题(2、括号序列))精讲
c++·gesp·小学生·学c++编程
jimy13 小时前
虚函数vtable,链接时看到构造函数,linker把符号地址写入vtable(三)
开发语言·c++
Logic1014 小时前
C语言/数据结构动态规划题解:爬楼梯(含坏台阶)——避开障碍物的路径计数
c语言·数据结构·动态规划·时间复杂度·空间复杂度·算法题·爬楼梯
潼心1412o4 小时前
C++初阶(长期更新)第9讲:string(上)
开发语言·c++
朝朝辞暮i4 小时前
C++ 第 39 章: 阶段性总复习——类、对象、构造、继承、this、指针与智能指针
开发语言·c++·算法·ros2
wuminyu4 小时前
Virtual Thread重投递至ForkJoinPool任务队列过程解析
java·linux·c语言·jvm·c++
All for pursuit.5 小时前
【回溯-6】79.单词搜索
数据结构·c++·算法·leetcode