https://leetcode-cn.com/problems/perfect-squares/submissions/

这是一道和硬币问题类似的拿/不拿/拿多少的问题,可以用动态规划解决,首先维护一个大小为n+1的数组a,a[i] = i (因为最坏情况是a[i] = i个1*1),然后求他的递推公式。

首先我们找出每个问题中的子问题,拿a[12]举例,不难发现
12 = 1 * 1 + 11 -> a[12] = a[11] + 1;
12 = 2 * 2 + 9 -> a[12] = a[9] + 1;
12 = 3 * 3 + 4 -> a[12] = a[4] + 1;
而 4 * 4 已经大于12了,所以对于a[i]我们只用考虑i - j*j >=0 的情况
所以a[12] = min(a[11] + 1, a[9] + 1, a[4] + 1)

到这里递推公式也就呼之欲出了:
a[i] = min(a[i - 1 * 1], a[i - 2 * 2], a[i - 3 * 3] ... a[i - j * j]) + 1; (i - j * j >= 0)

以下是代码

class Solution {
    public int numSquares(int n) {
        if(n < 0) return 0;
        int[] array = new int[n+1];
        for(int i=0; i<=n; i++){
            array[i] = i;
            for(int j=0; i - j*j >= 0; j++){
                array[i] = Math.min(array[i], array[i - j*j] + 1);
            }
        }
        return array[n];
    }
}

外层循环复杂度是O(n),内层是O(sqrt(n)),总复杂度是O(n(sqrt(n)))