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.

相关推荐
王哈哈^_^2 小时前
YOLO11实例分割训练任务——从构建数据集到训练的完整教程
人工智能·深度学习·算法·yolo·目标检测·机器学习·计算机视觉
Filotimo_2 小时前
SpringBoot3整合Druid数据源
java·spring boot
百锦再2 小时前
第18章 高级特征
android·java·开发语言·后端·python·rust·django
檐下翻书1732 小时前
从入门到精通:流程图制作学习路径规划
论文阅读·人工智能·学习·算法·流程图·论文笔记
乄bluefox2 小时前
Reactor 中的 doOnError 与 doOnCancel
java·reactor·rea
CoderYanger2 小时前
B.双指针——3194. 最小元素和最大元素的最小平均值
java·开发语言·数据结构·算法·leetcode·职场和发展·1024程序员节
SalvoGao2 小时前
Python学习 | 怎么理解epoch?
数据结构·人工智能·python·深度学习·学习
程序猿20233 小时前
项目结构深度解析:理解Spring Boot项目的标准布局和约定
java·spring boot·后端
RainbowSea3 小时前
内网穿透配置和使用
java·后端