$dp[i] = Math.min(dp[i],dp[i-j*j]+1);$
-
2.18
- 忘了 i-j*j 了
- 寄
-
2.4
- 难点一:忘了初始化 dp 数组全为最大值,因为有个与当前位置 dp 数组的 min 比较,不像打家劫舍
- 难点二:内 for 条件为
j*j<=i - 难点三:状态转移方程
class Solution {
// 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++){
// for(int j=1;j<=i*i;j++){
// dp[i] = Math.min(dp[i-1],dp[i-j*j]+1);
// }
// }
// return dp[n];
// }
// }- 12.4
dp[0]应该是0,因为凑整数0,需要0个数- 填充函数忘了
j=1;j*j<=i为第二层的结束条件(难点)
12
├─ 减 1² → 11
│ ├─ 减 1² → 10
│ │ ├─ 减 1² → 9 (1 step)
│ │ ├─ 减 4² ❌(超过)
│ │ └─ 减 9² → 1
│ └─ 减 4² → 7
│ └─ 减 4² → 3
└─ 减 4² → 8
└─ 减 4² → 4
└─ 减 4² → 0 ✅
+1 表示「在拼出前面的部分之后,又加上当前这个平方数」, 它是状态转移中“从旧状态走到新状态”的那一步。
- 事先填充
- i和j起点都为1
class Solution {
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++){
for(int j=1;j*j<=i;j++){
dp[i] = Math.min(dp[i],dp[i-j*j]+1);
}
}
return dp[n];
}
}