题目要求:
分析:
这道题利用动态规划来做,参考了一位大神的博客,传送门:LeetCode 279. Perfect Squares
我们创建一个长度为n + 1的数组dp表示最少的完全平方数,则可以得到一个递推关系式:
dp[i] = Math.min(dp[j] + dp[i - j], dp[i])
根据这个表达式就可以写代码了。
根据这位大神的分析,这个表达式是可以优化的,每个普通的数字都可以优化成一个完全平方数 + 一个普通数,则递推关系式就变为:
dp[i + j * j] = Math.min(dp[i] + 1, dp[i + j * j])
这样就避免了求开方的运算,代码的写法跟上述也差不多。
具体代码如下:
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 = 2; i <= n; i ++) {
int sqr = (int)Math.sqrt(i);
if(sqr * sqr == i) {
dp[i] = 1;
} else {
for(int j = 1; j <= i / 2; j ++) {
dp[i] = Math.min(dp[j] + dp[i - j], dp[i]);
}
}
}
return dp[n];
}
}
优化过后为:
class Solution {
public int numSquares(int n) {
int[] dp = new int[n + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
for(int i = 1; i * i <= n; i ++) {
dp[i * i] = 1;
}
for(int i = 1; i <= n; i ++) {
for(int j = 1; i + j * j <= n; j ++) {
dp[i + j * j] = Math.min(dp[i] + 1, dp[i + j * j]);
}
}
return dp[n];
}
}