题目大意:
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n = 12
输出: 3
解释: 12 = 4 + 4 + 4.
示例 2:
输入: n = 13
输出: 2
解释: 13 = 4 + 9.
解题思路:
方法一:
四平方定理(不太了解emmm)。
class Solution {
public:
int numSquares(int n) {
while (0 == n % 4) n /= 4;
if (7 == n % 8) return 4;
for (int i = 0; i * i < n; ++i) {
int j = pow(n - i * i, 0.5);
if (n == i * i + j * j) return !!i + !!j;
}
return 3;
}
};
方法二:
可以看做是背包问题进行求解:假设n=13,则找到小于等于n的完全平方数,分别是1,4,9。这三个数可以看作是货物的价值,货物的重量是1.
因此题目转化为:给定货物价值和重量,求当背包装满时的最小重量。
class Solution {
public:
int numSquares(int n) {
if (n < 4)
return n;
sqrtNum = int(sqrt(n));
vector<int> squareNums;
for (int i = 1; i <= sqrtNum; ++i)
squareNums.push_back(i * i);
vector<int> dp(n + 1, 0);
for (int i = 0; i < dp.size(); ++i){
dp[i] = i;
}
for (int i = 1; i < squareNums.size(); ++i){
for(int j = 1; j < dp.size(); ++j){
if (squareNums[i] - j >= 0){
dp[j] = min(dp[j], dp[squareNums[i] - j] + 1);
}
}
}
return dp.back();
}
};
方法三:
改进上述版本,不需要显式地求出每个n包含的完全平方数。
class Solution {
public:
int numSquares(int n) {
if (n < 4)
return n;
vector<int> nums(n + 1, INT_MAX);
nums[0] = 0;
nums[1] = 1;
for (int i = 0; i < nums.size(); ++i){
for(int j = 1; j * j <= i; ++j){
nums[i] = min(nums[i], nums[i - j * j] + 1);
}
}
return nums.back();
}
};