目录
问题描述:
给你一个整数 n
,返回 和为 n
的完全平方数的最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1
、4
、9
和 16
都是完全平方数,而 3
和 11
不是。
示例 1:
输入:n = 12 输出:3 解释:12 = 4 + 4 + 4
示例 2:
输入:n = 13 输出:2 解释:13 = 4 + 9
实现代码与解析:
动态规划(完全背包):
版本一(容易理解版):
class Solution {
public:
int numSquares(int n)
{
// 求出所以可能组成的值
vector<int> nums;
for(int i = 1; i <= sqrt(n); i++)
{
nums.push_back(i * i);
}
//完全背包问题
vector<int> dp(n + 1, INT_MAX);//dp数组
dp[0] = 0;//初始化
for(int i = 0; i < nums.size(); i++)
{
for(int j = nums[i]; j <= n; j++)
{
dp[j] = min(dp[j], dp[j - nums[i]] + 1);
}
}
return dp[n];
}
};
原理思路:
一个完全背包问题,与Leetcode:322. 零钱兑换(C++)_Cosmoshhhyyy的博客-优快云博客问题相似,这里我们的物品也就是要组成的数组是单独求出来的,具体写法可以看看上一个文章。
其组成需要的完全平方数肯定小于 n,所以我们遍历出来所有的可能值放入 nums 中备用。
然后就是完全背包的代码了,如果对于完全背包不懂,可以看看动态规划:0-1背包、完全背包问题 | 详细原理解释 | 代码及优化(C++)_Cosmoshhhyyy的博客-优快云博客_c++代码优化工具 这个文章,原理讲解的都很详细。
当然也可以不遍历出来,直接用背包的思路就可以了。也就是下面的版本二的代码。
版本二:
class Solution {
public:
int numSquares(int n)
{
//完全背包问题
vector<int> dp(n + 1, INT_MAX);//dp数组
dp[0] = 0;//初始化
for(int i = 1; i * i <= n; i++)
{
for(int j = i * i; j <= n; j++)
{
dp[j] = min(dp[j], dp[j - i * i] + 1);
}
}
return dp[n];
}
};
原理思路:
其实和上面是一样的,只不过就是直接用的 i * i 而没有单独求组成的数组而已。