这题一开始的想法是backtrack,但是任何只求数目不求具体路径的题目都是dp题(误)。所以,这题是dp题!
嗯,这一题的dp递归式其实是这样的
f(i) = min(f(i - j)) + 1 (j = 1 * 1, 2 * 2, 3 * 3.... j * j 的范围要小于i)
base case很简单,就是f(0) = 0。
原理就是,我们从下往上堆叠解。每一个解都是由一个子解和一个square number组成。这个子解就是当前数字减去那个square number所对应的子解。再求出这个过程里最小的那个数字,就是当前解。这个过程可以保证你的解或者子解都必然是square number构成的,而且是最小的。这其实也就是backtrack引申出来的dp解。根据上述算法,得到代码如下:
public int numSquares(int n) {
if (n < 1) return 0;
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];
}