1.题目描述:
给你一个整数n,返回和为n的完全平方数的最少数量。完全平方数是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和16都是完全平方数,而3和11不是。
2.动态规划:
解法与leetcode322. 零钱兑换几乎一样,物品变为了从1开始的完全平方数。
class Solution {
public int numSquares(int n) {
int max = (int)Math.sqrt(n);
int[] goods = new int[max];
for (int i = 0; i < goods.length; i++) {
goods[i] = (i + 1) * (i + 1);
}//建立物品(完全平方数)的数组
int[] dp = new int[n + 1];
for (int i = 0; i < dp.length; i++) {
dp[i] = Integer.MAX_VALUE;
}
dp[0] = 0;
for (int i = 0; i < max; i++) {//交换循环次序均可
for (int j = goods[i]; j <= n; j++) {
if (dp[j - goods[i]] != Integer.MAX_VALUE) dp[j] = Math.min(dp[j], dp[j - goods[i]] + 1);
}
}
return dp[n];
}
}
直接把物品数组元素的信息放到循环体之内,节省空间:
class Solution {
public int numSquares(int n) {
int[] dp = new int[n + 1];
for (int i = 0; i < dp.length; i++) {
dp[i] = Integer.MAX_VALUE;
}
dp[0] = 0;
for (int i = 1; i * i <= n; i++) {
for (int j = i * i; j <= n; j++) {
if (dp[j - i * i] != Integer.MAX_VALUE) dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
//这里可以直接dp[j] = Math.min(dp[j], dp[j - i * i] + 1),省略if判断,因为判断完全平方数的上一层必无整型最大值,因为即使全部是1必能构成n,与零钱兑换可能凑不成不同
}
}
return dp[n];
}
}
二刷:
class Solution {
public int numSquares(int n) {
int[] dp = new int[n + 1];
for (int i = 0; i < dp.length; i++) {
dp[i] = Integer.MAX_VALUE;
}
dp[0] = 0;
for (int i = 1; i * i <= n; i++) {
for (int j = i * i; j <= n; j++) {
dp[j] = Math.min(dp[j], dp[j - i * i] + 1);//可以直接省略if判断,因为判断完全平方数的上一层必无整型最大值,因为即使全部是1必能构成n,与零钱兑换可能凑不成不同
}
}
return dp[n];
}
}