-3

Problem Statement:

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.

Example 1:

Input: n = 12
Output: 3 
Explanation: 12 = 4 + 4 + 4.

Example 2:

Input: n = 13
Output: 2
Explanation: 13 = 4 + 9.

Using the following knowledge about squares (given below) we can implement the following solution.

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.
int numSquares(int n) {
    while (n % 4 == 0)
        n /= 4;
    if (n % 8 == 7)
        return 4;
    for (int a=0; a*a<=n; ++a) {
        int b = sqrt(n - a*a);
        if (a*a + b*b == n)
            return 1 + !!a;
    }
    return 3;
}

Question:

Can someone help me understand what exactly are we trying to achieve in following for loop? I'm a little lost here.

for (int a=0; a*a<=n; ++a) {
    int b = sqrt(n - a*a);
    if (a*a + b*b == n)
        return 1 + !!a;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
User1990
  • 161
  • 11
  • 2
    `return 1 + !!a;` is the same as `if(a == 0) return 1; else return 2;`. Then you have the 4 `return` values for the 4 possible cases. – dxiv Dec 22 '20 at 23:55
  • Thanks, but what are we achieving when we do `b = sqrt(n - a*a)` ? I specially don't understand why `n - a*a` ? – User1990 Dec 23 '20 at 00:01
  • That checks to see if `n` is a sum of two squares, which happens iff `n - a * a` is itself a perfect square for some `a`. – dxiv Dec 23 '20 at 00:04

1 Answers1

1

The loop is trying to find two squares that sum to n.

Rather than trying every combination of numbers to see if we can square them and they add up to n, we just loop through the possibilities for one of the numbers -- this is a. We square that with a*a, and subtract that from n. We then get the integer part of the square root of this difference, and this is b. If a2+b2 adds up to n, this is the pair of squares that we're looking for.

We need to calculate the sum of the squares in case n - a*a wasn't a perfect square. In that case its square root will have a fraction in it, which will be lost when we convert it to an integer. In other words, testing a*a+b*b == n allows us to determine whether the square root was an integer.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • thanks ! I did draw this on white board, but instead of using a tree/graph approach I used a recursive call approach to instantiate and write down all the possible calls for `n=13` and I ended up making life difficult for myself. I later on drew a tree out of it for `n=7`, it made more sense to me, along with your explanation of course ! appreciate the help ! – User1990 Dec 23 '20 at 07:02