整数拆分 | LeetCode-343 | 动态规划
1.题目描述
给定一个正整数 n
,将其拆分为 k
个 正整数 的和( k >= 2
),并使这些整数的乘积最大化。
返回 你可以获得的最大乘积 。
示例 1:
1 | 输入: n = 2 |
示例 2:
1 | 输入: n = 10 |
提示:
2 <= n <= 58
2.题解
2.1 动态规划
1 | class Solution { |
2.2 数论
解题思路:
设将整数$n$拆分为$a$个小数字:
$n=n_1+n_2+…+n_a$
本题等价于求解:
$\max(n_1\times n_2\times…\times n_a)$
以下数学推导总体分为两步:① 当所有拆分出的数字相等时,乘积最大。② 最优拆分数字为 3 。
拆分规则:
- 最优: 3 。把数字 n 可能拆为多个因子 3 ,余数可能为 0,1,2 三种情况。
- 次优: 2 。若余数为 2 ;则保留,不再拆为 1+1 。
- 最差: 1 。若余数为 1 ;则应把一份 3+1 替换为 2+2,因为 2×2>3×1。
算法流程:
- 当 n≤3 时,按照规则应不拆分,但由于题目要求必须拆分,因此必须拆出一个因子 1 ,即返回 n−1 。
- 当n>3时,求n除以3的 整数部分a和 余数部分b(即n=3a+b),并分为以下三种情况:
- 当 b=0 时,直接返回 3a;
- 当 b=1 时,要将一个 1+3 转换为 2+2,因此返回$3^{a−1}×4$;
- 当 b=2 时,返回$3^a×2$
代码实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22class Solution {
// 定义一个公共方法 integerBreak,它接受一个整数 n 作为参数
public int integerBreak(int n) {
// 如果 n 小于或等于 3,直接返回 n - 1 (除了 n = 2 时,其本身已经是最大乘积)
if (n <= 3) return n - 1;
// 计算 n 除以 3 的商
int a = n / 3;
// 计算 n 除以 3 的余数
int b = n % 3;
// 如果 n 能够被 3 整除,即余数为 0,则结果就是 3 的 a 次方
if (b == 0) return (int)Math.pow(3, a);
// 如果余数是 1,表示可以将一个 3 替换为 4 (因为 3 + 3 变为 2 + 2 + 3),从而得到更大的乘积
if (b == 1) return (int)Math.pow(3, a - 1) * 4;
// 如果余数是 2,则直接将两个 3 中的一个替换为 2 (因为 3 * 3 变为 3 * 2),这样不会减少乘积
return (int)Math.pow(3, a) * 2;
}
}
-------------本文结束感谢您的阅读-------------