给一个正整数 n, 找到若干个完全平方数(比如1, 4, 9, ... )使得他们的和等于 n。你需要让平方数的个数最少。
给出 n = 12
, 返回 3
因为 12 = 4 + 4 + 4
。
给出 n = 13
, 返回 2
因为 13 = 4 + 9
。
/*
采用动态规划实现。用 dp[i] 数组存储第 i 个数的完美平方数。
递推式为:dp[i] = Math.max(dp[j] + dp[i-j], dp[i],
认为 i 的完全平方数是从和为 i 的两个完全平方数 dp[j] 和 dp[i-j]之和,然后从中取最小。
*/
public class Solution {
public int numSquares(int n) {
int[] dp = new int[n+1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[1] = 1;
for(int i = 1; i <= n; i++) {
int sqr = (int)Math.sqrt(i);
//如果 i 本身是个平方数,就将 dp[i] 置1
if(sqr * sqr == i) {dp[i] = 1;}
else {
for(int j = 1; j <= i/2; j++) { //!j<=i/2
dp[i] = Math.min(dp[j] + dp[i-j], dp[i]); //从0开始遍历所有和为 i 的 dp,使得 dp[i]取最小
}
}
}
return dp[n];
}
}
/*
public class Solution {
public 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++){
// 从小到大找平方数bxb
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]);
}
}
return dp[n];
}
}*/