A number can always be represented as a sum of squares of other numbers. Note that 1 is a square and we can always break a number as (1*1 + 1*1 + 1*1 + …). Given a number n, find the minimum number of squares that sum to X.
Examples :
Input: n = 100
Output: 1
Explanation:
100 can be written as 102. Note that 100 can also be written as 52 + 52 + 52 + 52, but this representation requires 4 squares.
Input: n = 6
Output: 3
The idea is simple, we start from 1 and go to a number whose square is smaller than or equals n. For every number x, we recur for n-x. Below is the recursive formula.
If n = 1 and x*x <= n
Below is a simple recursive solution based on the above recursive formula.
C++
#include <bits/stdc++.h>
using namespace std;
int getMinSquares(unsigned int n)
{
if ( sqrt (n) - floor ( sqrt (n)) == 0)
return 1;
if (n <= 3)
return n;
int res = n;
for ( int x = 1; x <= n; x++)
{
int temp = x * x;
if (temp > n)
break ;
else
res = min(res, 1 + getMinSquares
(n - temp));
}
return res;
}
int main()
{
cout << getMinSquares(6);
return 0;
}
|
Java
import java.util.*;
import java.io.*;
class squares
{
static int getMinSquares( int n)
{
if (n <= 3 )
return n;
int res = n;
for ( int x = 1 ; x <= n; x++)
{
int temp = x * x;
if (temp > n)
break ;
else
res = Math.min(res, 1 +
getMinSquares(n - temp));
}
return res;
}
public static void main(String args[])
{
System.out.println(getMinSquares( 6 ));
}
}
|
Python3
def getMinSquares(n):
if n < = 3 :
return n;
res = n
for x in range ( 1 , n + 1 ):
temp = x * x;
if temp > n:
break
else :
res = min (res, 1 + getMinSquares(n
- temp))
return res;
print (getMinSquares( 6 ))
|
C#
using System;
class GFG
{
static int getMinSquares( int n)
{
if (n <= 3)
return n;
int res = n;
for ( int x = 1; x <= n; x++)
{
int temp = x * x;
if (temp > n)
break ;
else
res = Math.Min(res, 1 +
getMinSquares(n - temp));
}
return res;
}
public static void Main()
{
Console.Write(getMinSquares(6));
}
}
|
Javascript
<script>
function getMinSquares(n)
{
if (n <= 3)
return n;
let res = n;
for (let x = 1; x <= n; x++)
{
let temp = x * x;
if (temp > n)
break ;
else
res = Math.min(res,
1 + getMinSquares(n - temp));
}
return res;
}
document.write(getMinSquares(6));
</script>
|
PHP
<?php
function getMinSquares( $n )
{
if ( $n <= 3)
return $n ;
$res = $n ;
for ( $x = 1; $x <= $n ; $x ++)
{
$temp = $x * $x ;
if ( $temp > $n )
break ;
else
$res = min( $res , 1 +
getMinSquares( $n -
$temp ));
}
return $res ;
}
echo getMinSquares(6);
?>
|
Time Complexity: O(2^n)
Space Complexity: O(n) where n is the recursion stack space.
The time complexity of the above solution is exponential. If we draw the recursion tree, we can observe that many subproblems are solved again and again. For example, when we start from n = 6, we can reach 4 by subtracting one 2 times and by subtracting 2 one times. So the subproblem for 4 is called twice.
Since the same subproblems are called again, this problem has the Overlapping Subproblems property. So min square sum problem has both properties (see this and this) of a dynamic programming problem. Like other typical Dynamic Programming(DP) problems, recomputations of the same subproblems can be avoided by constructing a temporary array table[][] in a bottom-up manner. Below is a Dynamic programming-based solution.
C++
#include <bits/stdc++.h>
using namespace std;
int getMinSquares( int n)
{
if (n<=3)
return n;
int * dp = new int [n + 1];
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;
dp[3] = 3;
for ( int i = 4; i <= n; i++)
{
dp[i] = i;
for ( int x = 1; x <= ceil ( sqrt (i)); x++)
{
int temp = x * x;
if (temp > i)
break ;
else
dp[i] = min(dp[i], 1 +
dp[i - temp]);
}
}
int res = dp[n];
delete [] dp;
return res;
}
int main()
{
cout << getMinSquares(6);
return 0;
}
|
Java
import java.util.*;
import java.io.*;
class squares
{
static int getMinSquares( int n)
{
if (n <= 3 )
return n;
int dp[] = new int [n + 1 ];
dp[ 0 ] = 0 ;
dp[ 1 ] = 1 ;
dp[ 2 ] = 2 ;
dp[ 3 ] = 3 ;
for ( int i = 4 ; i <= n; i++)
{
dp[i] = i;
for ( int x = 1 ; x <= Math.ceil(
Math.sqrt(i)); x++)
{
int temp = x * x;
if (temp > i)
break ;
else
dp[i] = Math.min(dp[i], 1
+ dp[i - temp]);
}
}
int res = dp[n];
return res;
}
public static void main(String args[])
{
System.out.println(getMinSquares( 6 ));
}
}
|
Python3
from math import ceil, sqrt
def getMinSquares(n):
dp = [ 0 , 1 , 2 , 3 ]
for i in range ( 4 , n + 1 ):
dp.append(i)
for x in range ( 1 , int (ceil(sqrt(i))) + 1 ):
temp = x * x;
if temp > i:
break
else :
dp[i] = min (dp[i], 1 + dp[i - temp])
return dp[n]
print (getMinSquares( 6 ))
|
C#
using System;
class squares
{
static int getMinSquares( int n)
{
if (n <= 3)
return n;
int [] dp = new int [n + 1];
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;
dp[3] = 3;
for ( int i = 4; i <= n; i++)
{
dp[i] = i;
for ( int x = 1; x <= Math.Ceiling(
Math.Sqrt(i)); x++)
{
int temp = x * x;
if (temp > i)
break ;
else
dp[i] = Math.Min(dp[i], 1 +
dp[i - temp]);
}
}
int res = dp[n];
return res;
}
public static void Main(String[] args)
{
Console.Write(getMinSquares(6));
}
}
|
Javascript
<script>
function getMinSquares( n)
{
if (n <= 3)
return n;
var dp = new Array(n + 1);
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;
dp[3] = 3;
for ( var i = 4; i <= n; i++)
{
dp[i] = i;
for ( var x = 1; x <= Math.ceil(
Math.sqrt(i)); x++)
{
var temp = x * x;
if (temp > i)
break ;
else
dp[i] = Math.min(dp[i], 1 +
dp[i - temp]);
}
}
var res = dp[n];
return res;
}
document.write(getMinSquares(6));
</script>
|
PHP
<?php
function getMinSquares( $n )
{
$dp ;
$dp [0] = 0;
$dp [1] = 1;
$dp [2] = 2;
$dp [3] = 3;
for ( $i = 4; $i <= $n ; $i ++)
{
$dp [ $i ] = $i ;
for ( $x = 1; $x <= ceil (sqrt( $i ));
$x ++)
{
$temp = $x * $x ;
if ( $temp > $i )
break ;
else $dp [ $i ] = min( $dp [ $i ],
(1 + $dp [ $i - $temp ]));
}
}
$res = $dp [ $n ];
return $res ;
}
echo getMinSquares(6);
?>
|
Time Complexity: O(n*sqrtn)
Auxiliary Space: O(n)
Thanks to Gaurav Ahirwar for suggesting this solution.
Another Approach: (USING MEMOIZATION)
The problem can be solved using the memoization method (dynamic programming) as well.
Below is the implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int minCount( int n)
{
int * minSquaresRequired = new int [n + 1];
minSquaresRequired[0] = 0;
minSquaresRequired[1] = 1;
for ( int i = 2; i <= n; ++i)
{
minSquaresRequired[i] = INT_MAX;
for ( int j = 1; i - (j * j) >= 0; ++j)
{
minSquaresRequired[i]
= min(minSquaresRequired[i],
minSquaresRequired[i - (j * j)]);
}
minSquaresRequired[i] += 1;
}
int result = minSquaresRequired[n];
delete [] minSquaresRequired;
return result;
}
int main()
{
cout << minCount(6);
return 0;
}
|
Java
import java.util.*;
class GFG {
static int minCount( int n)
{
int [] minSquaresRequired = new int [n + 1 ];
minSquaresRequired[ 0 ] = 0 ;
minSquaresRequired[ 1 ] = 1 ;
for ( int i = 2 ; i <= n; ++i)
{
minSquaresRequired[i] = Integer.MAX_VALUE;
for ( int j = 1 ; i - (j * j) >= 0 ; ++j)
{
minSquaresRequired[i] = Math.min(minSquaresRequired[i], minSquaresRequired[i - (j * j)]);
}
minSquaresRequired[i] += 1 ;
}
int result = minSquaresRequired[n];
return result;
}
public static void main(String[] args) {
System.out.print(minCount( 6 ));
}
}
|
Python3
import sys
def minCount(n):
minSquaresRequired = [ 0 for i in range (n + 1 )];
minSquaresRequired[ 0 ] = 0 ;
minSquaresRequired[ 1 ] = 1 ;
for i in range ( 2 ,n + 1 ):
minSquaresRequired[i] = sys.maxsize;
j = 1
for j in range ( 1 ,i - (j * j)):
if (i - (j * j) > = 0 ):
minSquaresRequired[i] = min (minSquaresRequired[i], minSquaresRequired[i - (j * j)]);
else :
break
minSquaresRequired[i] + = 1 ;
result = minSquaresRequired[n];
return result;
if __name__ = = '__main__' :
print (minCount( 6 ));
|
C#
using System;
class GFG {
static int minCount( int n)
{
int [] minSquaresRequired = new int [n + 1];
minSquaresRequired[0] = 0;
minSquaresRequired[1] = 1;
for ( int i = 2; i <= n; ++i)
{
minSquaresRequired[i] = Int32.MaxValue;
for ( int j = 1; i - (j * j) >= 0; ++j)
{
minSquaresRequired[i] = Math.Min(minSquaresRequired[i], minSquaresRequired[i - (j * j)]);
}
minSquaresRequired[i] += 1;
}
int result = minSquaresRequired[n];
return result;
}
public static void Main(String[] args) {
Console.Write(minCount(6));
}
}
|
Javascript
<script>
function minCount(n)
{
let minSquaresRequired = new Array(n + 1);
minSquaresRequired[0] = 0;
minSquaresRequired[1] = 1;
for (let i = 2; i <= n; ++i) {
minSquaresRequired[i] = Number.MAX_VALUE;
for (let j = 1; i - (j * j) >= 0; ++j) {
minSquaresRequired[i]
= Math.min(minSquaresRequired[i],
minSquaresRequired[i - (j * j)]);
}
minSquaresRequired[i] += 1;
}
let result = minSquaresRequired[n];
return result;
}
document.write(minCount(6));
</script>
|
Another Approach:
This problem can also be solved by using graphs. Here is the basic idea of how it can be done.
We will use BFS (Breadth-First Search) to find the minimum number of steps from a given value of n to 0.
So, for every node, we will push the next possible valid path which is not visited yet into a queue and,
and if it reaches node 0, we will update our answer if it is less than the answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int numSquares( int n)
{
vector< int > visited(n + 1,0);
queue< pair< int , int > >q;
int ans = INT_MAX;
q.push({n,0});
visited[n] = 1;
while (!q.empty())
{
pair< int , int > p;
p = q.front();
q.pop();
if (p.first == 0)
ans=min(ans, p.second);
for ( int i = 1; i * i <= p.first; i++)
{
int path=(p.first - (i*i));
if (path >= 0 && ( !visited[path]
|| path == 0))
{
visited[path]=1;
q.push({path,p.second + 1});
}
}
}
return ans;
}
int main()
{
cout << numSquares(12);
return 0;
}
|
Java
import java.util.*;
import java.awt.Point;
class GFG
{
public static int numSquares( int n)
{
int visited[] = new int [n + 1 ];
Queue<Point> q = new LinkedList<>();
int ans = Integer.MAX_VALUE;
q.add( new Point(n, 0 ));
visited[n] = 1 ;
while (q.size() != 0 )
{
Point p = q.peek();
q.poll();
if (p.x == 0 )
ans = Math.min(ans, p.y);
for ( int i = 1 ; i * i <= p.x; i++)
{
int path = (p.x - (i * i));
if (path >= 0 && (visited[path] == 0 || path == 0 ))
{
visited[path] = 1 ;
q.add( new Point(path, p.y + 1 ));
}
}
}
return ans;
}
public static void main(String[] args)
{
System.out.println(numSquares( 12 ));
}
}
|
Python3
import sys
def numSquares(n) :
visited = [ 0 ] * (n + 1 )
q = []
ans = sys.maxsize
q.append([n, 0 ])
visited[n] = 1
while ( len (q) > 0 ) :
p = q[ 0 ]
q.pop( 0 )
if (p[ 0 ] = = 0 ) :
ans = min (ans, p[ 1 ])
i = 1
while i * i < = p[ 0 ] :
path = p[ 0 ] - i * i
if path > = 0 and (visited[path] = = 0 or path = = 0 ) :
visited[path] = 1
q.append([path,p[ 1 ] + 1 ])
i + = 1
return ans
print (numSquares( 12 ))
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class GFG{
public class Point
{
public int x, y;
public Point( int x, int y)
{
this .x = x;
this .y = y;
}
}
public static int numSquares( int n)
{
int []visited = new int [n + 1];
Queue q = new Queue();
int ans = 1000000000;
q.Enqueue( new Point(n, 0));
visited[n] = 1;
while (q.Count != 0)
{
Point p = (Point)q.Dequeue();
if (p.x == 0)
ans = Math.Min(ans, p.y);
for ( int i = 1; i * i <= p.x; i++)
{
int path = (p.x - (i * i));
if (path >= 0 && (visited[path] == 0 ||
path == 0))
{
visited[path] = 1;
q.Enqueue( new Point(path, p.y + 1));
}
}
}
return ans;
}
public static void Main( string [] args)
{
Console.Write(numSquares(12));
}
}
|
Javascript
function numSquares(n)
{
let visited = new Array(n + 1).fill(0);
let q = [];
let ans = Number.MAX_SAFE_INTEGER;
q.push([n, 0]);
visited[n] = 1;
while (q.length > 0)
{
let p = q[0];
q.shift();
if (p[0] == 0)
ans = Math.min(ans, p[1]);
let i = 1;
while (i * i <= p[0])
{
let path = p[0] - i * i;
if (path >= 0 && (visited[path] == 0 || path == 0) )
{
visited[path] = 1;
q.push([path,p[1] + 1]);
}
i += 1;
}
}
return ans;
}
console.log(numSquares(12));
|
The time complexity of the above problem is O(n)*sqrt(n) which is better than the Recursive approach.
Also, it is a great way to understand how BFS (Breadth-First Search) works.
Please write a if you find anything incorrect, or you want to share more information about the topic discussed above.
Another Approach:
This problem can also be solved using Dynamic programming (Bottom-up approach). The idea is like coin change 2 (in which we need to tell minimum number of coins to make an amount from given coins[] array), here an array of all perfect squares less than or equal to n can be replaced by coins[] array and amount can be replaced by n. Just see this as an unbounded knapsack problem, Let’s see an example:
For given input n = 6, we will make an array upto 4, arr : [1,4]
Here, answer will be (4 + 1 + 1 = 6) i.e. 3.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int numSquares( int n)
{
vector < int > arr;
int i = 1;
while (i*i <= n){
arr.push_back(i*i);
i++;
}
vector < int > dp(n+1, INT_MAX);
dp[n] = 0;
for ( int i = n-1; i>=0; i--){
for ( int j = 0; j<arr.size(); j++){
if (i + arr[j] <= n){
dp[i] = min(dp[i], dp[i+arr[j]]);
}
}
dp[i]++;
}
return dp[0];
}
int main()
{
cout << numSquares(12);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int numSquares( int n)
{
Vector <Integer> arr = new Vector<>();
int k = 1 ;
while (k * k <= n){
arr.add(k * k);
k++;
}
int []dp = new int [n + 1 ];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[n] = 0 ;
for ( int i = n - 1 ; i >= 0 ; i--)
{
for ( int j = 0 ; j < arr.size(); j++)
{
if (i + arr.elementAt(j) <= n)
{
dp[i] = Math.min(dp[i], dp[i+arr.elementAt(j)]);
}
}
dp[i]++;
}
return dp[ 0 ];
}
public static void main(String[] args)
{
System.out.print(numSquares( 12 ));
}
}
|
Python3
import sys
def numSquares(n):
arr = [];
k = 1 ;
while (k * k < = n):
arr.append(k * k);
k + = 1 ;
dp = [sys.maxsize for i in range (n + 1 )];
dp[n] = 0 ;
for i in range (n - 1 , - 1 , - 1 ):
for j in range ( len (arr)):
if (i + arr[j] < = n):
dp[i] = min (dp[i], dp[i + arr[j]]);
dp[i] + = 1 ;
return dp[ 0 ];
if __name__ = = '__main__' :
print (numSquares( 12 ));
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
static int numSquares( int n)
{
List < int > arr = new List< int >();
int k = 1;
while (k * k <= n){
arr.Add(k * k);
k++;
}
int []dp = new int [n + 1];
for ( int i = 0; i < n + 1; i++)
dp[i] = int .MaxValue;
dp[n] = 0;
for ( int i = n - 1; i >= 0; i--)
{
for ( int j = 0; j < arr.Count; j++)
{
if (i + arr[j] <= n)
{
dp[i] = Math.Min(dp[i], dp[i+arr[j]]);
}
}
dp[i]++;
}
return dp[0];
}
public static void Main(String[] args)
{
Console.Write(numSquares(12));
}
}
|
Javascript
<script>
function numSquares(n) {
var arr = new Array();
var k = 1;
while (k * k <= n) {
arr.push(k * k);
k++;
}
var dp = Array(n + 1).fill(Number.MAX_VALUE);
dp[n] = 0;
for (i = n - 1; i >= 0; i--) {
for (j = 0; j < arr.length; j++) {
if (i + arr[j] <= n) {
dp[i] = Math.min(dp[i], dp[i + arr[j]]);
}
}
dp[i]++;
}
return dp[0];
}
document.write(numSquares(12));
</script>
|
The time complexity of the above problem is O(n)*sqrt(n) as array will be made in sqrt(n) time and for loops for filling dp array will take n*sqrt(n) time atmost. The size of dp array will be n, so space complexity of this approach is O(n).
Another Approach: (Using Mathematics)
The solution is based on Lagrange’s Four Square Theorem.
According to the theorem, there can be atmost 4 solutions to the problem, i.e. 1, 2, 3, 4
Case 1:
Ans = 1 => This can happen if the number is a square number.
n = {a2 : a ∈ W}
Example : 1, 4, 9, etc.
Case 2:
Ans = 2 => This is possible if the number is the sum of 2 square numbers.
n = {a2 + b2 : a, b ∈ W}
Example : 2, 5, 18, etc.
Case 3:
Ans = 3 => This can happen if the number is not of the form 4k(8m + 7).
For more information on this : https://en.wikipedia.org/wiki/Legendre%27s_three-square_theorem
n = {a2 + b2 + c2 : a, b, c ∈ W} ⟷ n ≢ {4k(8m + 7) : k, m ∈ W }
Example : 6, 11, 12 etc.
Case 4:
Ans = 4 => This can happen if the number is of the form 4k(8m + 7).
n = {a2 + b2 + c2 + d2 : a, b, c, d ∈ W} ⟷ n ≡ {4k(8m + 7) : k, m ∈ W }
Example : 7, 15, 23 etc.
C++
#include <bits/stdc++.h>
using namespace std;
bool isSquare( int x)
{
int sqRoot = sqrt (x);
return (sqRoot * sqRoot == x);
}
int cntSquares( int n)
{
if (isSquare(n)) {
return 1;
}
for ( int i = 1; i <= ( int ) sqrt (n)+1; i++) {
if (isSquare(n - (i * i))) {
return 2;
}
}
while (n % 4 == 0) {
n >>= 2;
}
if (n % 8 == 7) {
return 4;
}
return 3;
}
int main()
{
cout << cntSquares(12) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG{
static boolean isSquare( int x)
{
int sqRoot = ( int )Math.sqrt(x);
return (sqRoot * sqRoot == x);
}
static int cntSquares( int n)
{
if (isSquare(n)) {
return 1 ;
}
for ( int i = 1 ; i <= ( int )Math.sqrt(n)+ 1 ; i++) {
if (isSquare(n - (i * i))) {
return 2 ;
}
}
while (n % 4 == 0 ) {
n >>= 2 ;
}
if (n % 8 == 7 ) {
return 4 ;
}
return 3 ;
}
public static void main(String[] args)
{
System.out.print(cntSquares( 12 ) + "\n" );
}
}
|
Python3
import math
def isSquare(x):
sqRoot = int (math.sqrt(x));
return (sqRoot * sqRoot = = x);
def cntSquares(n):
if (isSquare(n)):
return 1 ;
for i in range ( 1 , int (math.sqrt(n)) + 1 ):
if (isSquare(n - (i * i))):
return 2 ;
while (n % 4 = = 0 ):
n >> = 2 ;
if (n % 8 = = 7 ):
return 4 ;
return 3 ;
if __name__ = = '__main__' :
print (cntSquares( 12 ) , "");
|
C#
using System;
public class GFG{
static bool isSquare( int x)
{
int sqRoot = ( int )Math.Sqrt(x);
return (sqRoot * sqRoot == x);
}
static int cntSquares( int n)
{
if (isSquare(n)) {
return 1;
}
for ( int i = 1; i <= ( int )Math.Sqrt(n)+1; i++) {
if (isSquare(n - (i * i))) {
return 2;
}
}
while (n % 4 == 0) {
n >>= 2;
}
if (n % 8 == 7) {
return 4;
}
return 3;
}
public static void Main(String[] args)
{
Console.Write(cntSquares(12) + "\n" );
}
}
|
Javascript
<script>
function isSquare(x) {
var sqRoot = parseInt( Math.sqrt(x));
return (sqRoot * sqRoot == x);
}
function cntSquares(n)
{
if (isSquare(n)) {
return 1;
}
for ( var i = 1; i <= parseInt( Math.sqrt(n))+1; i++) {
if (isSquare(n - (i * i))) {
return 2;
}
}
while (n % 4 == 0) {
n >>= 2;
}
if (n % 8 == 7) {
return 4;
}
return 3;
}
document.write(cntSquares(12) + "\n" );
</script>
|
Time Complexity: O(sqrtn)
Auxiliary Space: O(1)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!