【Hot 100 刷题计划】 LeetCode 279. 完全平方数 | C++ 动态规划 (完全背包)

LeetCode 279. 完全平方数

📌 题目描述

题目级别:中等

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

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

  • 示例 1:

    输入:n = 12

    输出:3

    解释:12 = 4 + 4 + 4

  • 示例 2:

    输入:n = 13

    输出:2

    解释:13 = 4 + 9


💡 破题思路:动态规划的完全背包模型

这道题本质上是一个完全背包问题的变形:

  • 背包容量 :数字 n
  • 物品 :所有的完全平方数(1,4,9,16...1, 4, 9, 16...1,4,9,16...)。
  • 物品重量:完全平方数的数值。
  • 物品价值:数量统统算作 1 个(因为题目要求"最少数量")。
  • 特殊限制:每个物品可以无限次使用。

状态定义:

定义 dp[i] 为:和为 i 的完全平方数的最少数量。

状态转移方程:

对于当前的数字 i,它可以由之前的某个数字加上一个"完全平方数 j×jj \times jj×j"组合而来。

所以我们只需要回头看看之前的状态 dp[i - j*j],然后在这个基础上加 1(也就是加上当前这个完全平方数)。

为了求最少数量,我们在所有可能的回头路径中取最小值:

dp[i] = min(dp[i], dp[i - j * j] + 1)

巧妙的初始化:

  • dp[0] = 0:凑成 0 需要 0 个数。
  • 对于其他的 dp[i],我们需要初始化为一个极大值。这里非常巧妙地初始化为 n + 1。因为即使全用 1 来凑,最多也只需要 n 个数,所以 n + 1 在这里就起到了"无穷大"的作用,同时完美避免了使用 INT_MAX 时发生 INT_MAX + 1 导致的整数溢出问题!

💻 C++ 代码实现

cpp 复制代码
class Solution {
public:
    int numSquares(int n) {
        // 使用变长数组 (或可以替换为 vector<int> dp(n + 1, n + 1))
        int dp[n + 10];
        
        dp[0] = 0;
        // 巧妙初始化为 n + 1,相当于安全版的无穷大
        for (int i = 1; i <= n; i ++ ) dp[i] = n + 1;

        // 遍历背包容量 (从 1 到 n)
        for (int i = 1; i <= n; i ++ )
        {
            // 遍历物品 (完全平方数 j*j)
            for (int j = 1; j * j <= i; j ++ )
            {
                // 状态转移:取当前值与"刨除完全平方数后剩余值的最少数量 + 1"的较小者
                dp[i] = min(dp[i], dp[i - j * j] + 1);
            }
        }

        return dp[n];
    }
};
相关推荐
郝学胜_神的一滴4 小时前
CMake 034:生成器表达式:解耦构建时序、精简分支逻辑的终极利器
c++·cmake
见过夏天20 小时前
C++ 基础入门完全指南
c++
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
To_OC3 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC3 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
BadBadBad__AK3 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
卷无止境3 天前
Eigen 库如何借助 OpenMP 加速计算
c++·后端
卷无止境3 天前
OpenMPI、MPICH 与 OpenMP:关系、核心概念与架构全解
c++·后端
To_OC4 天前
LC 994 腐烂的橘子:人人都说是 BFS 入门题,我却写了三遍才过
javascript·算法·leetcode
To_OC4 天前
LC 200 岛屿数量:经典 DFS 入门题,我第一次写居然连方向都搞错了
javascript·算法·leetcode