Skip to main content

Perfect Squares - LeetCode Daily Challenge

Prerna Sharma

Given an integer n, return the least number of perfect square numbers that sum to n.

perfect square is an integer that is the square of an integer; in other words, it is the product of some integer with itself. For example, 149, and 16 are perfect squares while 3 and 11 are not.

Example 1

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

Example 2

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

Try here before watching the video.

Video Explanation

Java Code

class Solution {

    private int solve(int n, int[] dp) {
        if(n <= 1) {
            return n;
        }
        
        if(dp[n] != -1) {
            return dp[n];
        }

        int count = Integer.MAX_VALUE;
        for(int i = 1; i <= Math.sqrt(n); i++) {
            int temp = 1 + solve(n - (i * i), dp);
            count = Math.min(temp, count);
        }
        return dp[n] = count;
    }

    public int numSquares(int n) {
        int[] dp = new int[n + 1];
        Arrays.fill(dp, -1);
        return solve(n, dp);    
    }
}

C++ Code

class Solution {
private:
    int solve(int n, vector<int>& dp) {
        if (n <= 1) {
            return n;
        }

        if (dp[n] != -1) {
            return dp[n];
        }

        int count = INT_MAX;
        for (int i = 1; i <= sqrt(n); i++) {
            int temp = 1 + solve(n - (i * i), dp);
            count = min(temp, count);
        }
        return dp[n] = count;
    }

public:
    int numSquares(int n) {
        vector<int> dp(n + 1, -1);
        return solve(n, dp);
    }
};

Python Code

class Solution:
    def solve(self, n: int, dp: List[int]) -> int:
        if n <= 1:
            return n
        
        if dp[n] != -1:
            return dp[n]
        
        count = float('inf')
        for i in range(1, int(n ** 0.5) + 1):
            temp = 1 + self.solve(n - (i * i), dp)
            count = min(temp, count)
        
        dp[n] = count
        return count

    def numSquares(self, n: int) -> int:
        dp = [-1] * (n + 1)
        return self.solve(n, dp)

Javascript Code

var numSquares = function(n) {
    const solve = (n, dp) => {
        if (n <= 1) {
            return n;
        }

        if (dp[n] !== -1) {
            return dp[n];
        }

        let count = Number.MAX_SAFE_INTEGER;
        for (let i = 1; i <= Math.sqrt(n); i++) {
            const temp = 1 + solve(n - (i * i), dp);
            count = Math.min(temp, count);
        }
        dp[n] = count;
        return count;
    };

    const dp = new Array(n + 1).fill(-1);
    return solve(n, dp);
};

Go Code

func solve(n int, dp []int) int {
	if n <= 1 {
		return n
	}

	if dp[n] != -1 {
		return dp[n]
	}

	count := math.MaxInt32
	for i := 1; i <= int(math.Sqrt(float64(n))); i++ {
		temp := 1 + solve(n - (i * i), dp)
		count = int(math.Min(float64(temp), float64(count)))
	}
	dp[n] = count
	return count
}

func numSquares(n int) int {
	dp := make([]int, n + 1)
	for i := range dp {
		dp[i] = -1
	}
	return solve(n, dp)
}

Complexity Analysis

Time Complexity: O(N * sqrt(N)), The time complexity of this solution can be analyzed in terms of the number of subproblems being solved. In the worst case, each recursive call can result in exploring all integers up to the square root of the given number N. Therefore, the time complexity can be expressed as O(N * sqrt(N)), where N is the input number.
Space Complexity: O(N), The space complexity is determined by the size of the memoization array dp, which has a length of N + 1. Hence, the space complexity is O(N) since it grows linearly with the input size.