给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...
)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n =12
输出: 3 解释:12 = 4 + 4 + 4.
示例 2:
输入: n =13
输出: 2 解释:13 = 4 + 9.
解题思路:
动态规划:
第一种方法,对dp求解的顺序是固定的,只初始化了第一个值为0,那么在循环里计算,每次增加一个dp数组的长度,里面那个for循环一次循环结束就算好当前i由几个完全平方数组成,直到增加到第n个。
第二种方法中,我们建立一个长度为n+1的一维dp数组,将第一个值初始化为0,其余值都初始化为INT_MAX, i从0循环到n,j从1循环到i+j*j <= n的位置,然后每次更新dp[i+j*j]的值,动态更新dp数组,其中dp[i]表示正整数i能少能由多个完全平方数组成,那么我们求n,就是返回dp[n]即可,这里更新dp数组的顺序是打乱的。
public static int numSquares1(int n) {
int[] dp = new int[n + 1];
dp[0] = 0;
for (int i = 1; i <= n; ++i) {
int min = Integer.MAX_VALUE;
int j = 1;
while (i - j*j >= 0) {
min = Math.min(min, dp[i - j*j] + 1);
j++;
}
dp[i] = min;
}
return dp[n];
}
public static int numSquares2(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 = 0; i <= n; ++i) {
for (int j = 1; i+j*j <= n; j++) {
dp[i+j*j]=Math.min(dp[i+j*j], dp[i]+1);
System.out.println(i+j*j+" "+dp[i+j*j]);
}
}
return dp[n];
}