Article / 文章

LeetCode 第343题:整数拆分

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。返回你可以获得的最大乘积。

📖 文章摘要

本文详细解析LeetCode第343题“整数拆分”,这是一道中等难度的动态规划题目。文章提供了动态规划和数学方法两种解法,包含C#、Python、C++三种语言实现,配有详细的算法分析和性能对比。适合想要提升动态规划和数学思维能力的程序员。

核心知识点: 动态规划、数学、贪心算法
难度等级: 中等
推荐人群: 具有基础算法知识,想要提升动态规划能力的开发者

题目描述

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。返回你可以获得的最大乘积。

示例

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1

示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36

提示

  • 2 <= n <= 58

解题思路

方法一:动态规划

使用动态规划求解最优拆分方案。

关键点:

  • 定义dp[i]表示整数i拆分后的最大乘积
  • 考虑所有可能的拆分方案
  • 状态转移方程:dp[i] = max(dp[i], max(j * (i-j), j * dp[i-j]))

具体步骤:

  1. 创建dp数组
  2. 初始化dp[2] = 1
  3. 遍历每个数字i
  4. 对每个i,遍历所有可能的拆分点j
  5. 更新dp[i]为最大值

时间复杂度:O(n^2) 空间复杂度:O(n)

方法二:数学方法

通过数学分析可知,尽可能多地使用3进行拆分可以得到最大乘积。

关键点:

  • 尽可能拆分出3
  • 最后剩余4时不再拆分
  • 处理特殊情况2和3

具体步骤:

  1. 处理特殊情况n=2和n=3
  2. 计算可以拆分出多少个3
  3. 处理余数情况

时间复杂度:O(1) 空间复杂度:O(1)

图解思路

动态规划分析表

数字n 最优拆分 最大乘积 计算过程
2 1+1 1 1×1=1
3 1+2 2 1×2=2
4 2+2 4 2×2=4
5 2+3 6 2×3=6
6 3+3 9 3×3=9
7 3+4 12 3×4=12

数学方法分析

规律总结:
1. n=2: 1×1=1
2. n=3: 1×2=2
3. n=4: 2×2=4
4. n>4: 尽可能多地拆分出3
   例如:10 = 3 + 3 + 4
   3×3×4 = 36 > 3×3×3×1 = 27

代码实现

C# 实现

public class Solution {
    // 方法一:动态规划
    public int IntegerBreak(int n) {
        int[] dp = new int[n + 1];
        dp[2] = 1;
        
        for (int i = 3; i <= n; i++) {
            for (int j = 1; j < i; j++) {
                dp[i] = Math.Max(dp[i], Math.Max(j * (i - j), j * dp[i - j]));
            }
        }
        
        return dp[n];
    }
    
    // 方法二:数学方法
    public int IntegerBreakMath(int n) {
        if (n == 2) return 1;
        if (n == 3) return 2;
        
        int quotient = n / 3;
        int remainder = n % 3;
        
        if (remainder == 0) {
            return (int)Math.Pow(3, quotient);
        } else if (remainder == 1) {
            return (int)Math.Pow(3, quotient - 1) * 4;
        } else {
            return (int)Math.Pow(3, quotient) * 2;
        }
    }
}

Python 实现

class Solution:
    # 方法一:动态规划
    def integerBreak(self, n: int) -> int:
        dp = [0] * (n + 1)
        dp[2] = 1
        
        for i in range(3, n + 1):
            for j in range(1, i):
                dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]))
                
        return dp[n]
    
    # 方法二:数学方法
    def integerBreakMath(self, n: int) -> int:
        if n == 2:
            return 1
        if n == 3:
            return 2
            
        quotient = n // 3
        remainder = n % 3
        
        if remainder == 0:
            return 3 ** quotient
        elif remainder == 1:
            return 3 ** (quotient - 1) * 4
        else:
            return 3 ** quotient * 2

C++ 实现

class Solution {
public:
    // 方法一:动态规划
    int integerBreak(int n) {
        vector<int> dp(n + 1);
        dp[2] = 1;
        
        for (int i = 3; i <= n; i++) {
            for (int j = 1; j < i; j++) {
                dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]));
            }
        }
        
        return dp[n];
    }
    
    // 方法二:数学方法
    int integerBreakMath(int n) {
        if (n == 2) return 1;
        if (n == 3) return 2;
        
        int quotient = n / 3;
        int remainder = n % 3;
        
        if (remainder == 0) {
            return pow(3, quotient);
        } else if (remainder == 1) {
            return pow(3, quotient - 1) * 4;
        } else {
            return pow(3, quotient) * 2;
        }
    }
};

执行结果

C# 实现

  • 执行用时:24 ms
  • 内存消耗:25.1 MB

Python 实现

  • 执行用时:32 ms
  • 内存消耗:14.9 MB

C++ 实现

  • 执行用时:0 ms
  • 内存消耗:6.1 MB

性能对比

语言 执行用时 内存消耗 特点
C# 24 ms 25.1 MB 代码结构清晰
Python 32 ms 14.9 MB 实现简洁
C++ 0 ms 6.1 MB 性能最优

代码亮点

  1. 🎯 动态规划思路清晰
  2. 💡 数学方法高效
  3. 🔍 边界条件处理完善
  4. 🎨 代码简洁优雅

常见错误分析

  1. 🚫 忘记处理特殊情况n=2和n=3
  2. 🚫 动态规划初始化错误
  3. 🚫 数学方法中的余数处理错误
  4. 🚫 整数溢出问题

解法对比

解法 时间复杂度 空间复杂度 优点 缺点
动态规划 O(n^2) O(n) 通用性强 效率较低
数学方法 O(1) O(1) 高效 不易理解

相关题目


📖 系列导航

🔥 算法专题合集 - 查看完整合集

📢 关注合集更新:点击上方合集链接,关注获取最新题解!目前已更新至第343题。


💬 互动交流

感谢大家耐心阅读到这里!希望这篇题解能够帮助你更好地理解和掌握这道算法题。

如果这篇文章对你有帮助,请:

  • 👍 点个赞,让更多人看到这篇文章
  • 📁 收藏文章,方便后续查阅复习
  • 🔔 关注作者,获取更多高质量算法题解
  • 💭 评论区留言,分享你的解题思路或提出疑问

你的支持是我持续分享的动力!

💡 一起进步:算法学习路上不孤单,欢迎一起交流学习!