LeetCode 279: Perfect Squares

LeetCode 279: Perfect Squares

    • [1. 📌 Problem Links](#1. 📌 Problem Links)
    • [2. 🧠 Solution Overview](#2. 🧠 Solution Overview)
    • [3. 🟢 Solution 1: Dynamic Programming (Bottom-Up)](#3. 🟢 Solution 1: Dynamic Programming (Bottom-Up))
      • [3.1. Algorithm Idea](#3.1. Algorithm Idea)
      • [3.2. Key Points](#3.2. Key Points)
      • [3.3. Java Implementation](#3.3. Java Implementation)
      • [3.4. Complexity Analysis](#3.4. Complexity Analysis)
    • [4. 🟡 Solution 2: Optimized Dynamic Programming](#4. 🟡 Solution 2: Optimized Dynamic Programming)
      • [4.1. Algorithm Idea](#4.1. Algorithm Idea)
      • [4.2. Key Points](#4.2. Key Points)
      • [4.3. Java Implementation](#4.3. Java Implementation)
      • [4.4. Complexity Analysis](#4.4. Complexity Analysis)
    • [5. 🔵 Solution 3: Mathematical Approach (Lagrange's Four-Square Theorem)](#5. 🔵 Solution 3: Mathematical Approach (Lagrange's Four-Square Theorem))
      • [5.1. Algorithm Idea](#5.1. Algorithm Idea)
      • [5.2. Key Points](#5.2. Key Points)
      • [5.3. Java Implementation](#5.3. Java Implementation)
      • [5.4. Complexity Analysis](#5.4. Complexity Analysis)
    • [6. 📊 Solution Comparison](#6. 📊 Solution Comparison)
    • [7. 💡 Summary](#7. 💡 Summary)

2. 🧠 Solution Overview

This problem requires finding the minimum number of perfect square numbers that sum to a given integer n. A perfect square is an integer that is the square of an integer (e.g., 1, 4, 9, 16). Below are the main approaches:

Method Key Idea Time Complexity Space Complexity
Dynamic Programming DP array storing min squares for each number O(n√n) O(n)
Space-Optimized DP Similar but more efficient implementation O(n√n) O(n)
Mathematical Approach Using Lagrange's four-square theorem O(√n) O(1)

3. 🟢 Solution 1: Dynamic Programming (Bottom-Up)

3.1. Algorithm Idea

We use a DP array where dp[i] represents the minimum number of perfect squares that sum to i. The key insight is that any number i can be expressed as i = (i - j×j) + j×j for some j, where j×j is a perfect square. Therefore, the solution for i depends on solutions for smaller numbers .

3.2. Key Points

  • State Definition : dp[i] = minimum perfect squares that sum to i
  • State Transition : dp[i] = min(dp[i], dp[i - j×j] + 1) for all j where j×j ≤ i
  • Initialization :
    • dp[0] = 0 (base case: 0 requires 0 squares)
    • Initialize all other dp[i] to a large value (e.g., Integer.MAX_VALUE)
  • Processing Order: Process numbers from 1 to n sequentially

3.3. Java Implementation

java 复制代码
class Solution {
    public int numSquares(int n) {
        // Create DP array with initial large values
        int[] dp = new int[n + 1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0; // Base case
        
        // Precompute all perfect squares up to n
        int maxSquare = (int) Math.sqrt(n);
        int[] squares = new int[maxSquare + 1];
        for (int i = 1; i <= maxSquare; i++) {
            squares[i] = i * i;
        }
        
        // Fill DP table
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= maxSquare; j++) {
                if (squares[j] <= i) {
                    dp[i] = Math.min(dp[i], dp[i - squares[j]] + 1);
                }
            }
        }
        
        return dp[n];
    }
}

3.4. Complexity Analysis

  • Time Complexity : O(n√n) - Outer loop O(n), inner loop O(√n)
  • Space Complexity : O(n) - For the DP array

4. 🟡 Solution 2: Optimized Dynamic Programming

4.1. Algorithm Idea

This is a more optimized version that eliminates the need to precompute all perfect squares. It uses the same DP concept but with more efficient inner loop conditions .

4.2. Key Points

  • Direct Computation : Calculate j×j on the fly instead of precomputing
  • Early Termination : Inner loop runs only while j×j ≤ i
  • Efficient Initialization : Initialize dp[i] = i (worst case: all 1's)

4.3. Java Implementation

java 复制代码
class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n + 1];
        
        for (int i = 1; i <= n; i++) {
            // Worst case: all 1's (i = 1+1+...+1)
            dp[i] = i;
            
            // Try all perfect squares ≤ i
            for (int j = 1; j * j <= i; j++) {
                dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
            }
        }
        
        return dp[n];
    }
}

4.4. Complexity Analysis

  • Time Complexity : O(n√n) - Same as previous DP approach
  • Space Complexity : O(n) - For the DP array

5. 🔵 Solution 3: Mathematical Approach (Lagrange's Four-Square Theorem)

5.1. Algorithm Idea

This approach uses Lagrange's four-square theorem, which states that every natural number can be represented as the sum of four integer squares. The algorithm checks if the number can be represented by 1, 2, or 3 squares before defaulting to 4 .

5.2. Key Points

  • Check for 1 square : If n is a perfect square, return 1
  • Check for 4 squares : If n = 4^k × (8m + 7) for some k, m, return 4
  • Check for 2 squares : Try all i from 1 to √n to see if n - i² is a perfect square
  • Default case: If none of the above, return 3

5.3. Java Implementation

java 复制代码
class Solution {
    public int numSquares(int n) {
        // Check if n is a perfect square
        if (isPerfectSquare(n)) {
            return 1;
        }
        
        // Check four-square condition: n = 4^k × (8m + 7)
        if (isFourSquare(n)) {
            return 4;
        }
        
        // Check if n is sum of two squares
        for (int i = 1; i * i <= n; i++) {
            if (isPerfectSquare(n - i * i)) {
                return 2;
            }
        }
        
        // Default to three squares
        return 3;
    }
    
    private boolean isPerfectSquare(int num) {
        int sqrt = (int) Math.sqrt(num);
        return sqrt * sqrt == num;
    }
    
    private boolean isFourSquare(int n) {
        while (n % 4 == 0) {
            n /= 4;
        }
        return n % 8 == 7;
    }
}

5.4. Complexity Analysis

  • Time Complexity : O(√n) - Much faster than DP approaches
  • Space Complexity : O(1) - Constant space

6. 📊 Solution Comparison

Solution Time Space Pros Cons
Standard DP O(n√n) O(n) Intuitive, guaranteed optimal Slower for large n
Optimized DP O(n√n) O(n) More efficient, simpler code Still polynomial time
Mathematical O(√n) O(1) Optimal time, elegant Harder to understand

7. 💡 Summary

For the Perfect Squares problem:

  • Learning & Understanding : Start with Standard DP to grasp the fundamental pattern
  • Interviews & Practical Use : Optimized DP offers the best balance of understandability and efficiency
  • Production & Performance : Mathematical Approach provides optimal O(√n) performance

The key insight for DP is recognizing the optimal substructure - the solution for each number can be built from solutions for smaller numbers by considering all possible perfect squares .

The search for perfect squares reveals the beautiful interplay between mathematical theory and computational practice - where deep number theory theorems can provide elegant solutions to seemingly complex optimization problems.

相关推荐
星火开发设计10 小时前
C++ 预处理指令:#include、#define 与条件编译
java·开发语言·c++·学习·算法·知识
Hx_Ma1610 小时前
SpringMVC返回值
java·开发语言·servlet
Yana.nice11 小时前
openssl将证书从p7b转换为crt格式
java·linux
独自破碎E11 小时前
【滑动窗口+字符计数数组】LCR_014_字符串的排列
android·java·开发语言
mit6.82411 小时前
dijk|tire+floyd+dp %
算法
想逃离铁厂的老铁11 小时前
Day55 >> 并查集理论基础 + 107、寻找存在的路线
java·服务器
Jack_David11 小时前
Java如何生成Jwt之使用Hutool实现Jwt
java·开发语言·jwt
瑞雪兆丰年兮11 小时前
[从0开始学Java|第六天]Java方法
java·开发语言
独自破碎E11 小时前
【总和拆分 + 双变量遍历】LCR_012_寻找数组的中心下标
数据结构·算法
WBluuue11 小时前
Codeforces 1076 Div3(ABCDEFG)
c++·算法