leetcode 279,完全平方数
题目描述
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n = 12
输出: 3
解释: 12 = 4 + 4 + 4.
示例 2:
输入: n = 13
输出: 2
解释: 13 = 4 + 9
方法一:动态规划
构造最优子结构
for (int i = 1; i <= n; i++) {
//得到i的平方根
int sqrt = (int) Math.sqrt((double) i);
for (int j = 1; j <= sqrt; j++) {
//这里是最优子结构
dp[i] = Math.min( dp[i] , dp[ i - j*j ] );
}
}
解释
dp[i]
代表的是第i个数字组成的最少完全平方数个数
完全平方数有:1,4,9,16
分别是1,2,3,4
的平方
那么我们可以给出dp[i]
的最小值是,i
之前的减去平方根数的dp,
例如12
sqrt(12) = 3
就代表着,12
里面所包含的最大平方根为3
,
那么组成12
所需要的最少的完全平方根个数就可以这样找
dp[12 - 1*1] + 1
代表从12往前数,中间空1的平方个个数的dp[j],加上 1 ,代表又加了一个1的平方的数字
dp[12 - 2*2] + 1
代表从12往前数,中间空2的平方个个数的dp[j], 加上 1 ,代表又加了一个2的平方的数字
dp[12 - 3*3] + 1
代表从12往前数,中间空3的平方个个数的dp[j], 加上 1 ,代表又加了一个3的平方的数字
这样,找出他们中间最小的那个即可。
通过代码:
public int numSquares(int n) {
int[] dp = new int[n + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for (int i = 1; i <= n; i++) {
int sqrt = (int) Math.sqrt((double) i);
for (int j = 1; j <= sqrt; j++) {
dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
}
}
return dp[n];
}