問題:數組
Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...
) which sum to n.函數
For example, given n = 12
, return 3
because 12 = 4 + 4 + 4
; given n = 13
, return 2
because 13 = 4 + 9
.code
解決:遞歸
① 給定一個正整數,求它最少能由幾個徹底平方數組成。本解法找到一個規律。it
【四平方和定理】任意一個正整數都可表示爲4個之內的平方數之和。io
class Solution { //2ms
public int numSquares(int n) {
while(n % 4 == 0) n /= 4;
if (n % 8 == 7) return 4;
for (int i = 0;i * i <= n;i ++){
int j = (int) Math.sqrt(n - i * i);
if (i * i + j * j == n){
return (i > 0 && j > 0) ? 2 : 1;
}
}
return 3;
}
}ast
② 遞歸方法。遍歷全部比n小的徹底平方數,而後對n與徹底平方數的差值遞歸調用函數,目的是不斷更新最終結果,直到找到最小的那個。class
class Solution { //326ms
public int numSquares(int n) {
int count = n;
int num = 2;
while(num * num <= n){
int a = n / (num * num);
int b = n % (num * num);
count = Math.min(count,a + numSquares(b));
num ++;
}
return count;
}
}遍歷
③ 動態規劃。若是一個數x能夠表示爲一個任意數a加上一個平方數bxb,也就是x=a+bxb,那麼能組成這個數x最少的平方數個數,就是能組成a最少的平方數個數加上1(由於b*b已是平方數了)。時間 O(N^2) ,空間 O(N)。方法
class Solution { //64ms public int numSquares(int n) { int[] dp = new int[n + 1]; Arrays.fill(dp, Integer.MAX_VALUE);//將全部非平方數的結果置爲最大,保證以後比較的時候不被選中 for (int i = 0;i * i <= n;i ++){//將全部平方數的結果置爲1 dp[i * i] = 1; } for (int i = 0;i <= n;i ++){//從小到大找任意數i for (int j = 0; i + j * j <= n;j ++){//從小到大找平方數j*j dp[i + j * j] = Math.min(dp[i] + 1,dp[i + j * j]); } } return dp[n]; } }