import java.util.Arrays;
/**
* 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.
*
* Tags: Dynamic Programming, Breadth-first Search, Math
* Similar Problems: (E) Count Primes, (M) Ugly Number II
*/
public class PerfectSquares {
/**
* A natural number is...
*
* 1. a square if and only if each prime factor occurs to an even power in the number's prime factorization.
* 2. a sum of two squares if and only if each prime factor that's 3 modulo 4 occurs to an even power in the
* number's prime factorization.
* 3. a sum of three squares if and only if it's not of the form 4a(8b+7) with integers a and b.
* 4. a sum of four squares. Period. No condition. You never need more than four.
*/
public int numSquares1(int n) {
while (n % 4 == 0)
n /= 4;
if (n % 8 == 7)
return 4;
for (int a = 0; a * a <= n; a++) {
int b = (int) Math.sqrt(n - a * a);
if (a * a + b * b == n) {
return 1 + (a > 0 ? 1 : 0);
}
}
return 3;
}
/**
* DP, bottom-up
*/
public int numSquares2(int n) {
int[] res = new int[n + 1];
Arrays.fill(res, Integer.MAX_VALUE);
res[0] = 0;
for (int i = 0; i <= n; i++) {
for (int j = 1; j * j <= i; j++) {
res[i] = Math.min(res[i], res[i - j * j] + 1);
}
}
return res[n];
}
public static void main(String[] args) {
PerfectSquares ps = new PerfectSquares();
int res = ps.numSquares1(13);
System.out.println("res: " + res);
res = ps.numSquares2(13);
System.out.println("res: " + res);
}
}