# 279. Perfect Squares 完全平方数

@TOC

## # 题目描述

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.

Example 1:

``````Input: n = 12
Output: 3
Explanation: 12 = 4 + 4 + 4.
``````

Example 2:

``````Input: n = 13
Output: 2
Explanation: 13 = 4 + 9.
``````

## # 解题方法

### # 四平方和定理

C++代码如下：

``````class Solution {
public:
int numSquares(int n) {
while (n % 4 == 0) n /= 4;
if (n % 8 == 7) return 4;
for (int a = 0; a * a < n; ++a) {
int b = sqrt(n - a * a);
if (a * a + b * b == n) {
return !!a + !!b;
}
}
return 3;
}
};
``````

java代码如下：

``````public class Solution {
public int numSquares(int n) {
while (n % 4 == 0) n /= 4;
if (n % 8 == 7) return 4;
for (int a = 0; a * a < n; a++) {
for (int b = 0; b * b <= n - a * a; b++) {
if (a * a + b * b == n) {
return (a > 0 ? 1 : 0) + (b > 0 ? 1 : 0);
}
}
}
return 3;
}
}
``````

### # 动态规划

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

C++代码如下：

``````class Solution {
public:
int numSquares(int n) {
//dp[i] means how many perfect squres it needs.
vector<int> dp(n + 1, INT_MAX);
dp[0] = 0;
for (int i = 0; i <= n; ++i) {
for (int j = 1; i + j * j <= n; ++j) {
dp[i + j * j] = min(dp[i + j * j], dp[i] + 1);
}
}
return dp[n];
}
};
``````

Java代码如下：

``````public static int numSquares(int n) {
int[] dp = new int[n + 1];
// 将所有非平方数的结果置最大，保证之后比较的时候不被选中
Arrays.fill(dp, Integer.MAX_VALUE);
// 将所有平方数的结果置1
for (int i = 0; i * i <= n; i++) {
dp[i * i] = 1;
}
// 从小到大找任意数a
for (int a = 0; a <= n; a++) {
// 从小到大找平方数bｘb
for (int b = 0; a + b * b <= n; b++) {
// 因为a+b*b可能本身就是平方数，所以我们要取两个中较小的
dp[a + b * b] = Math.min(dp[a] + 1, dp[a + b * b]);
System.out.println(a + b * b + ":--" + Arrays.toString(dp));
}
}
return dp[n];
}
``````

``````0:--[1, 1, 2147483647, 2147483647, 1, 2147483647, 2147483647, 2147483647, 2147483647, 1, 2147483647]
1:--[1, 1, 2147483647, 2147483647, 1, 2147483647, 2147483647, 2147483647, 2147483647, 1, 2147483647]
4:--[1, 1, 2147483647, 2147483647, 1, 2147483647, 2147483647, 2147483647, 2147483647, 1, 2147483647]
9:--[1, 1, 2147483647, 2147483647, 1, 2147483647, 2147483647, 2147483647, 2147483647, 1, 2147483647]
1:--[1, 1, 2147483647, 2147483647, 1, 2147483647, 2147483647, 2147483647, 2147483647, 1, 2147483647]
2:--[1, 1, 2, 2147483647, 1, 2147483647, 2147483647, 2147483647, 2147483647, 1, 2147483647]
5:--[1, 1, 2, 2147483647, 1, 2, 2147483647, 2147483647, 2147483647, 1, 2147483647]
10:--[1, 1, 2, 2147483647, 1, 2, 2147483647, 2147483647, 2147483647, 1, 2]
2:--[1, 1, 2, 2147483647, 1, 2, 2147483647, 2147483647, 2147483647, 1, 2]
3:--[1, 1, 2, 3, 1, 2, 2147483647, 2147483647, 2147483647, 1, 2]
6:--[1, 1, 2, 3, 1, 2, 3, 2147483647, 2147483647, 1, 2]
3:--[1, 1, 2, 3, 1, 2, 3, 2147483647, 2147483647, 1, 2]
4:--[1, 1, 2, 3, 1, 2, 3, 2147483647, 2147483647, 1, 2]
7:--[1, 1, 2, 3, 1, 2, 3, 4, 2147483647, 1, 2]
4:--[1, 1, 2, 3, 1, 2, 3, 4, 2147483647, 1, 2]
5:--[1, 1, 2, 3, 1, 2, 3, 4, 2147483647, 1, 2]
8:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
5:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
6:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
9:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
6:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
7:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
10:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
7:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
8:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
8:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
9:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
9:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
10:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
10:--[1, 1, 2, 3, 1, 2, 3, 4, 2, 1, 2]
2
``````

``````class Solution {
public:
int numSquares(int n) {
// dp[i] means how many perfect squres it needs.
vector<int> dp;
dp.push_back(0);
for (int i = 1; i <= n; ++i) {
int val = INT_MAX;
for (int j = 1; j * j <= i; ++j) {
val = min(val, dp[i - j * j] + 1);
}
dp.push_back(val);
}
return dp[n];
}
};
``````

## # 日期

2015/11/15 20:43:42 2016/4/29 21:05:01 2019 年 1 月 7 日 —— 新的一周开始啦啦啊