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

题目分析

题目中“n 至少可以拆分为两个正整数的和”,这个条件说明了 n 是大于 1 的整数。

对 7 来说,可以拆成 3+4,最大乘积是 12。

对 8 来说,可以拆成 3+3+2,最大乘积是 18。

解法 1: 动态规划

状态数组dp[i]表示:数字 i 拆分为至少两个正整数之和的最大乘积。为了方便计算,dp 的长度是 n + 1,值初始化为 1。

显然dp[2]等于 1,外层循环从 3 开始遍历,一直到 n 停止。内层循环 j 从 1 开始遍历,一直到 i 之前停止,它代表着数字 i 可以拆分成 j + (i - j)。但 j * (i - j)不一定是最大乘积,因为i-j不一定大于dp[i - j](数字i-j拆分成整数之和的最大乘积),这里要选择最大的值作为 dp[i] 的结果。

空间复杂度是 \(O(N)\),时间复杂度是 \(O(N^2)\)。代码实现如下:

// ac地址:https://leetcode-cn.com/problems/integer-break/
// 原文地址:https://xxoo521.com/2020-02-15-integer-break/ /**
* @param {number} n
* @return {number}
*/
var integerBreak = function(n) {
const dp = new Array(n + 1).fill(1); for (let i = 3; i <= n; ++i) {
for (let j = 1; j < i; ++j) {
dp[i] = Math.max(dp[i], j * (i - j), j * dp[i - j]);
}
} return dp[n];
};

解法 2: 贪心法

力扣上此题给出了提示:多试试几个例子,找出规律。下面说下我找规律的思路。

前面提到:8 拆分为 3+3+2,此时乘积是最大的。然后就推测出来一个整数,要拆成多个 2 和 3 的和,保证乘积最大。原理很容易理解,因为 2 和 3 可以合成任何数字,例如5=2+3,但是5 < 2*3;例如6=3+3,但是6<3*3。所以根据贪心算法,就尽量将原数拆成更多的 3,然后再拆成更多的 2,保证拆出来的整数的乘积结果最大。

但上面的解法还有不足。如果整数 n 的形式是 3k+1,例如 7。按照上面规则,会拆分成“3 + 3 + 1”。但是在乘法操作中,1 是没作用的。此时,应该将 1 和 3 变成 4,也就是“3 + 3 + 1”变成“3 + 4”。此时乘积最大。

综上所述,算法的整体思路是:

  • n 除 3 的结果为 a,余数是 b
  • 当 b 为 0,直接将 a 个 3 相乘
  • 当 b 为 1,将(a-1)个 3 相乘,再乘以 4
  • 当 b 为 2,将 a 个 3 相乘,再乘以 2

空间复杂度是 O(1),时间复杂度是 O(1)。代码实现如下:

// ac地址:https://leetcode-cn.com/problems/integer-break/
// 原文地址:https://xxoo521.com/2020-02-15-integer-break/ /**
* @param {number} n
* @return {number}
*/
var integerBreak = function(n) {
if (n === 2) return 1;
if (n === 3) return 2;
// a的含义:n能拆成的3的个数
const a = Math.floor(n / 3);
const b = n % 3; // n是3的倍数
if (b === 0) return Math.pow(3, a);
// n是 3k + 1,例如7。拆成3、3、1。由于有1对结果无法有贡献,所以最后的3、1换成4
if (b === 1) return Math.pow(3, a - 1) * 4;
return Math.pow(3, a) * 2;
};

如果想了解详细的数学推理,请参考《Leetcode 343:整数拆分(最详细的解法!!!)》

更多资料

  • LeetCode 343.整数拆分 - JavaScript的更多相关文章

    1. LeetCode 343. 整数拆分(Integer Break) 25

      343. 整数拆分 343. Integer Break 题目描述 给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化. 返回你可以获得的最大乘积. 每日一算法2019/5/2 ...

    2. Java实现 LeetCode 343 整数拆分(动态规划入门经典)

      343. 整数拆分 给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化. 返回你可以获得的最大乘积. 示例 1: 输入: 2 输出: 1 解释: 2 = 1 + 1, 1 × ...

    3. leetcode 343 整数拆分

      1.这个题拿到之后没有什么思路,此时就应该考虑暴力法.然而每次不知道要拆成几份,没办法用循环,所以想到用递归. 如图所示进行递归,显然有很多重复的计算,所以用自底向上的动态规划. 2.还有一个问题就是 ...

    4. 前端与算法 leetcode 7. 整数反转

      目录 # 前端与算法 leetcode 7. 整数反转 题目描述 概要 提示 解析 解法 算法 传入测试用例的运行结果 执行结果 GitHub仓库 # 前端与算法 leetcode 7. 整数反转 题 ...

    5. HDU 4651 Partition(整数拆分)

      题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4651 题意:给出n.求其整数拆分的方案数. i64 f[N]; void init(){    f[0 ...

    6. LightOJ 1336 Sigma Function(数论 整数拆分推论)

      --->题意:给一个函数的定义,F(n)代表n的所有约数之和,并且给出了整数拆分公式以及F(n)的计算方法,对于一个给出的N让我们求1 - N之间有多少个数满足F(x)为偶数的情况,输出这个数. ...

    7. LightOJ 1341 Aladdin and the Flying Carpet(整数拆分定理)

      分析:题目并不难理解,就是一些细节上的优化需要我们注意,我在没有优化前跑了2000多MS,优化了一些细节后就是400多MS了,之前还TLE了好几次. 方法:将整数拆分为质因子以后,表达为这样的形式,e ...

    8. HDU1028 (整数拆分)

      Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

    9. LeetCode:整数转罗马数字【12】

      LeetCode:整数转罗马数字[12] 题目描述 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 10 ...

    随机推荐

    1. UGUI源码之Graphic

      Graphic是用来显示图像的一个抽象类,是MaskableGraphic的父类,而MaskableGraphic是Image.RawImage.Text的父类. Graphic继承于UIBehavi ...

    2. 生成TFRecord文件完整代码实例

      import os import json def get_annotation_dict(input_folder_path, word2number_dict): label_dict = {} ...

    3. rest实践1

      REST 即表述性状态传递,是一种针对网络应用的设计和开发,可以降低开发的复杂性.是主流的Web服务实现方案. 表述性状态转移是一组构架约束条件和原则,满足这些约束条件和原则的应用程序和设计就是RES ...

    4. Tarjin + 缩点

      链接:https://www.nowcoder.com/acm/contest/81/C来源:牛客网 题目描述 给出一个 0 ≤ N ≤ 105 点数.0 ≤ M ≤ 105 边数的有向图, 输出一个 ...

    5. Trailhead Lightning 学习 一

      计划学习一下莱特宁,从最基本的开始学习,脚踏实地.不忘初心,牢记使命,以下是查阅的资料. 简介 在此Salesforce教程中,将阐述Salesforce Lightning的基础知识,并了解Sale ...

    6. Linux下Tomcat,mysql安装包及教程整合,

        前段时间孔老师给了一个虚拟机,自己瞎捣鼓,装了Tomcat和mysql,捣鼓了好几天,把一些安装包和试过还不错的博客整理出来:  老师给的已经装好了Linux系统和JDK. Tomcat9安装包 ...

    7. java自定义注解学习(注解处理器)

      如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了.使用注解的过程中,很重要的一部分就是创建于使用注解处理器.Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处 ...

    8. LeetCode 858 镜面反射

      题目 有一个特殊的正方形房间,每面墙上都有一面镜子.除西南角以外,每个角落都放有一个接受器,编号为 0, 1,以及 2. 正方形房间的墙壁长度为 p,一束激光从西南角射出,首先会与东墙相遇,入射点到接 ...

    9. nodejs 执行 最近 发现 nodejs 执行的 是非等待的。

      上一步结果 没有完成 下一步就执行了 结果就 不行

    10. Windos下的一些命令集合

      由于在CMD模式下(也就是命令行)有较多的有用的命令.以下是自己平时所记录下来的以帮助平时的任务. 1. 显示计算机的操作系统 wmic os get osarchitecture /value