动态规划,找到前几个状态做更新。
从题可看出又是一道dp,只要找到一个最大的平方数,然后往回退到上个状态,然后再用回退的状态加回去这个平方数即加上这一种。注意这里的所含平方数并不是随着数字变大而变大的,因此还要加多一层循环做遍历的维护,目的是找到的平方数少。
java
class Solution {
public int numSquares(int n) {
int[] f = new int[n + 1];
for (int i = 1; i <= n; i++) {
f[i] = Integer.MAX_VALUE;
for (int j = 1; j * j <= i; j++) {
f[i] = Math.min(f[i], f[i - j * j]+1);//通过减去一个平方数对前面已经遍历的f[i]进行筛选
}
}
return f[n];
}
}
这里对f[i]做了频繁更新,实际只需要在后面更新一次即可,在做比较时可以用一个临时变量去存,这样就可以优化一下维护状态的数组了。
java
class Solution {
public int numSquares(int n) {
int[] f = new int[n + 1];
for (int i = 1; i <= n; i++) {
int minn = Integer.MAX_VALUE;
for (int j = 1; j * j <= i; j++) {
minn = Math.min(minn, f[i - j * j]);//通过减去一个平方数对前面已经遍历的f[i]进行筛选
}
f[i] = minn + 1;//更新当前数时加回去j*j这种情况
}
return f[n];
}
}
然后也可以换一下内外层循环,先去生成所有完全平方数,然后做更新。
时间复杂度:O(n√n)
,空间复杂度:O(n)。
java
class Solution {
public int numSquares(int n) {
int[] f = new int[n + 1];
Arrays.fill(f, Integer.MAX_VALUE);
f[0] = 0;
for (int i = 1; i * i <= n; i++) {
for (int j = i * i; j <= n; j++) {
f[j] = Math.min(f[j], f[j - i * i] + 1);
}
}
return f[n];
}
}
在做dp时,学会找到状态间的关系,也要注意维护状态的数组优化。