Bird
Raised Fist0
Interview Prepdp-knapsackmediumGoogleAmazon

Perfect Squares

Choose your preparation mode4 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
📋
Problem

Imagine you want to represent a number as a sum of perfect squares, like breaking a chocolate bar into square pieces with minimal cuts.

Given an integer n, return the least number of perfect square numbers that sum to n. A perfect square is an integer that is the square of an integer (e.g., 1, 4, 9, 16, ...). Input: integer n. Output: integer representing the minimum count of perfect squares summing to n.

1 ≤ n ≤ 10^5
Edge cases: n = 1 → output 1 (smallest input)n = 0 → output 0 (no squares needed)n = 10000 → output 1 (perfect square itself)
</>
IDE
def numSquares(n: int) -> int:public int numSquares(int n)int numSquares(int n)function numSquares(n)
def numSquares(n):
    # Write your solution here
    pass
class Solution {
    public int numSquares(int n) {
        // Write your solution here
        return 0;
    }
}
#include <vector>
using namespace std;

int numSquares(int n) {
    // Write your solution here
    return 0;
}
function numSquares(n) {
    // Write your solution here
}
0/9
Common Bugs to Avoid
Wrong: 1Greedy approach picking largest square once, ignoring multiple usage.Iterate over all squares j*j <= i and update dp[i] = min(dp[i], 1 + dp[i - j*j]) allowing repeated use.
Wrong: 3Confusing 0/1 knapsack with unbounded knapsack, using each square only once.Allow multiple usage by using unbounded knapsack recurrence: dp[i] = min(dp[i], 1 + dp[i - j*j]) for all j.
Wrong: 0Missing base case for n=0 or incorrect initialization.Set dp[0] = 0 explicitly to handle zero input correctly.
Wrong: 2Off-by-one error in dp array indexing or incomplete iteration.Ensure dp array covers all indices from 0 to n inclusive and loops run correctly.
Wrong: TLEUsing brute force recursion without memoization or bottom-up DP.Implement bottom-up DP with precomputed squares to achieve O(n * sqrt(n)) time.
Test Cases
t1_01basic
Input{"n":12}
Expected3

12 = 4 + 4 + 4 (three perfect squares)

t1_02basic
Input{"n":13}
Expected2

13 = 4 + 9 (two perfect squares)

t2_01edge
Input{"n":0}
Expected0

No squares needed to sum to zero.

t2_02edge
Input{"n":1}
Expected1

1 = 1 (one perfect square)

t2_03edge
Input{"n":10000}
Expected1

10000 = 100^2 (one perfect square)

t3_01corner
Input{"n":2}
Expected2

2 = 1 + 1 (two perfect squares)

t3_02corner
Input{"n":7}
Expected4

7 = 4 + 1 + 1 + 1 (four perfect squares)

t3_03corner
Input{"n":23}
Expected4

23 = 9 + 9 + 4 + 1 (four perfect squares)

t4_01performance
Input{"n":100000}
⏱ Performance - must finish in 2000ms

n=100000, O(n * sqrt(n)) DP must complete within 2 seconds.

Practice

(1/5)
1. Consider the following Python function implementing the Target Sum problem using bottom-up DP with offset indexing. What is the returned value when calling findTargetSumWays([1, 2], 1)?
easy
A. 1
B. 3
C. 0
D. 2

Solution

  1. Step 1: Trace initial dp array

    total=3, offset=3, dp=[0,0,0,1,0,0,0] (index 3 corresponds to sum 0)
  2. Step 2: Process num=1 and num=2 updating dp

    After num=1, dp counts ways to reach sums -1 and 1. After num=2, dp counts ways to reach sums -3,-1,1,3. dp[target+offset]=dp[1+3]=dp[4]=2.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Two ways: +1-2 and -1+2 sum to 1 [OK]
Hint: Offset indexing maps sums to dp indices [OK]
Common Mistakes:
  • Off-by-one errors in indexing dp array
2. The following code attempts to count the number of combinations to make change. Which line contains a subtle bug that causes it to count permutations instead of combinations?
medium
A. Line 5: inner loop iterating backwards over amounts
B. Line 4: outer loop over coins
C. Line 2: dp initialization
D. Line 6: updating dp[w] with dp[w - coin]

Solution

  1. Step 1: Understand iteration order effect

    Iterating amounts backwards causes dp to count permutations, not combinations.
  2. Step 2: Identify bug line

    Line 5 iterates w from amount down to coin, which breaks combination counting logic.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Forward iteration over amounts is required to count combinations correctly [OK]
Hint: Check direction of inner loop iteration [OK]
Common Mistakes:
  • Using backward iteration in 1D dp
  • Misplacing dp[0] initialization
3. What is the time complexity of the bottom-up dynamic programming solution for the integer break problem shown below?
def integer_break(n):
    dp = [0] * (n + 1)
    dp[1] = 1
    for i in range(2, n + 1):
        max_product = 0
        for j in range(1, i):
            max_product = max(max_product, max(j, dp[j]) * max(i - j, dp[i - j]))
        dp[i] = max_product
    return dp[n]
medium
A. O(n log n) time
B. O(n) time
C. O(2^n) time
D. O(n^2) time

Solution

  1. Step 1: Identify loops

    Outer loop runs from 2 to n (≈ n iterations). Inner loop runs from 1 to i (up to n iterations).
  2. Step 2: Calculate total operations

    Nested loops yield roughly 1 + 2 + ... + n ≈ n(n+1)/2 = O(n^2) operations.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Double nested loops with linear bounds -> quadratic time [OK]
Hint: Nested loops with linear bounds usually mean O(n²) [OK]
Common Mistakes:
  • Confusing with O(n) by ignoring inner loop
  • Thinking recursion stack adds exponential time here
4. Suppose the problem is modified so that each coin can be used at most once (0/1 knapsack variant). Which of the following changes to the original code correctly counts the number of combinations?
hard
A. Change inner loop to iterate amounts backward (from amount down to coin) to avoid reuse
B. Change inner loop to iterate amounts forward (from coin to amount) as in original code
C. Use recursion without memoization to explore all subsets
D. Use greedy approach picking largest coins first

Solution

  1. Step 1: Understand 0/1 knapsack constraints

    Each coin can be used once, so dp updates must avoid reuse within same iteration.
  2. Step 2: Identify correct iteration order

    Iterating amounts backward ensures dp[w] uses dp[w - coin] from previous iteration, preventing reuse.
  3. Step 3: Evaluate other options

    Forward iteration allows reuse; recursion without memoization is inefficient; greedy is incorrect.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Backward iteration is standard for 0/1 knapsack to avoid reuse [OK]
Hint: Backward iteration prevents reuse in 0/1 knapsack [OK]
Common Mistakes:
  • Using forward iteration causing reuse
  • Relying on greedy or naive recursion
5. Suppose the coin change problem is modified so that each coin can only be used at most once (0/1 knapsack variant). Which of the following changes to the bottom-up DP approach correctly solves this variant?
hard
A. Use a 2D dp array where dp[i][j] represents minimum coins to make amount j using first i coins, iterating coins outer and amounts inner
B. Sort coins and greedily pick largest coins without repetition until amount is reached
C. Keep the same 1D dp array and iterate coins inside the amount loop as before (unbounded usage)
D. Use the same 1D dp but iterate amounts outer and coins inner, updating dp[j] only if dp[j - coin] was from previous iteration

Solution

  1. Step 1: Understand the 0/1 usage constraint

    Each coin can be used once, so we must track usage per coin, requiring 2D dp.
  2. Step 2: Identify correct DP structure

    2D dp with dp[i][j] = min coins to make j using first i coins ensures no reuse; iterate coins outer, amounts inner.
  3. Step 3: Why other options fail

    Keep the same 1D dp array and iterate coins inside the amount loop as before (unbounded usage) allows unlimited reuse; B is greedy and incorrect; D misuses 1D dp which is for unbounded usage.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    0/1 knapsack requires 2D dp to track coin usage [OK]
Hint: 0/1 knapsack needs 2D dp to prevent reuse [OK]
Common Mistakes:
  • Using unbounded knapsack DP for 0/1 problem
  • Assuming greedy works for minimum coins