题目描述:给定一个正整数 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. Redis-CAP定理和BASE理论(二)

      CAP理论概述 1998 年来自柏克莱加州大学的计算机科学家 埃里克.布鲁尔(Eric Brewer) 提出分布式系统的三个基本指标:Consistency(一致性).Availability(可用性 ...

    2. 原生javascript 元素依次掉落及上升

      一.实现原理: ① 通过onoff开关,判断元素是往下走 还是往上走,并在每次清除定时器后,把onoff 设为 !onoff,以便下次点击做判断 ②move函数的运用 二.代码 <!DOCTYP ...

    3. 基于 HTML5 + WebGL 的3D无人机 展示

      前言 近年来,无人机的发展越发迅速,既可民用于航拍,又可军用于侦察,涉及行业广泛,也被称为“会飞的照相机”.但作为军事使用,无人机的各项性能要求更加严格.重要.本系统则是通过 Hightopo 的   ...

    4. 关于java php go 中AES加解密秘钥长度问题

      今天心血来朝,想用go把php中的一个小功能重写一下,但在解密aes加密的数据时碰到了个坑! php的mcrypt拓展(貌似php7.1版本以上不支持了)提供了aes的加解密: 而且php aes 的 ...

    5. JS中使用FormData上传图片

      <!DOCTYPE html> <html> <head> <meta name="viewport" content="wid ...

    6. DbCommand :执行超时已过期。完成操作之前已超时或服务器未响应。

      问题:“Timeout 时间已到.在操作完成之前超时时间已过或服务器未响应.”的解决方法 在一个链接数据库的时候,老是出现超时的错误:执行超时已过期.完成操作之前已超时或服务器未响应. 就是给这个链接 ...

    7. 关于爬虫的日常复习(7)—— DOM操作及selenium库

    8. 实验四:划分多个VLAN

      1.配置图 2.配置命令 Switch1.Switch2.Switch3的配置是一样的,如下所示:(可直接复制交换机,可以只配置一次) 通过命令查看配置: Switch0的配置如下: 通过命令查看tr ...

    9. python接口自动化测试 - openpyxl基本使用

      前言 当你做接口自动化测试时,测试用例逐渐变多情况下,如果所有测试用例都通过代码管理将会使得代码十分臃肿,而且维护成本会很高: 所以我们一般会通过Excel去管理所有的测试用例,而openpyxl库提 ...

    10. 双指针,BFS与图论(一)

      (一)双指针 1.日志统计 小明维护着一个程序员论坛.现在他收集了一份”点赞”日志,日志共有 N 行. 其中每一行的格式是: ts id 表示在 ts 时刻编号 id 的帖子收到一个”赞”. 现在小明 ...