🎨Now live: Try our Free AI Image Generation Feature

Description
Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.
Intuition
To solve this problem, we can use a dynamic programming approach. The idea is to build up a solution for n by using solutions for smaller numbers. Specifically, for each number num from 1 to n, we can find the minimum number of perfect squares that sum to num by considering all perfect squares less than or equal to num.
Approach
- Memoization Initialization:
- Create a memoization array
memoof size10001and initialize all values to-1. This array will store the minimum number of perfect squares that sum to each index. - Recursive Function:
- Define a helper function
dp(num, memo)that returns the minimum number of perfect squares that sum tonum. - Base cases: - Ifnum < 0, return a large number (10000) because it is an invalid case. - Ifnum == 0, return0because no squares are needed to sum to zero. - Ifmemo[num] != -1, return the memoized result to avoid redundant calculations. - For eachifrom1to100, compute the minimum number of squares needed fornum - i*iand updatemini. - Memoize the result fornum. - Main Function:
- Call the helper function
dp(n, memo)to get the result.
Complexity
Time Complexity:
O(n * sqrt(n))
- There are
nstates and for each state, we loop up tosqrt(n).
Space Complexity:
O(n)
- The memoization array takes up
O(n)space.
Code
C++
class Solution {
public:
int numSquares(int n) {
vector memo(10001, -1);
return dp(n, memo);
}
private:
int dp(int num, vector& memo) {
if (num < 0) return 10000;
if (num == 0) return 0;
if (memo[num] != -1) return memo[num];
int mini = 100000;
for (int i = 1; i <= 100; i++) {
mini = min(mini, 1 + dp(num - i * i, memo));
}
return memo[num] = mini;
}
}; Python
class Solution:
def numSquares(self, n: int) -> int:
if n <= 0:
return 0
queue = deque([n])
visited = set([n])
level = 0
while queue:
level += 1
size = len(queue)
for _ in range(size):
current = queue.popleft()
for i in range(1, int(current**0.5) + 1):
remainder = current - i*i
if remainder == 0:
return level
if remainder not in visited:
visited.add(remainder)
queue.append(remainder)
return levelJava
class Solution {
public int numSquares(int n) {
int[] memo = new int[10001];
Arrays.fill(memo, -1);
return dp(n, memo);
}
private int dp(int num, int[] memo) {
if (num < 0) return 10000;
if (num == 0) return 0;
if (memo[num] != -1) return memo[num];
int mini = 100000;
for (int i = 1; i <= 100; i++) {
mini = Math.min(mini, 1 + dp(num - i * i, memo));
}
memo[num] = mini;
return mini;
}
}JavaScript
var numSquares = function (n) {
let memo = Array(10001).fill(-1);
return dp(n, memo);
};
function dp(num, memo) {
if (num < 0) return 10000;
if (num === 0) return 0;
if (memo[num] !== -1) return memo[num];
let mini = 100000;
for (let i = 1; i <= 100; i++) {
mini = Math.min(mini, 1 + dp(num - i * i, memo));
}
return memo[num] = mini;
}