leetcode 343. Integer Break(dp和math方法)

探讨了将正整数n分解成至少两个正整数的和,以使这些整数的乘积最大化的两种方法:动态规划和数学推导。通过实例说明,如输入10,输出最大乘积36。数学方法更高效,利用e为基底的乘积特性,确定3为最佳分解基数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get.

Example 1:

Input: 2
Output: 1
Explanation: 2 = 1 + 1, 1 × 1 = 1.
Example 2:

Input: 10
Output: 36
Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36.

给一个正整数n,把n至少分解成2个整数,使分解的整数乘积最大

思路:
(1)dp
比如10分解成2个整数的时候,可以分解成以下组合
1 * 9, 2* 8, 3 * 7, 4 * 6, 5 * 5,6* 4, 7 * 3, 8 * 2, 9 * 1
从这中间先选最大的

然后比如3 * 7, 7还可以进一步分解成[1 * 6, 2 * 5, 3 * 4, 4 * 3, 5 * 2, 6 * 1]
7分解的整数乘积的最大值在从1~10的过程中已经计算过了,再用到时只需要调用dp

所以dp[i] = max(两个数的积(比如3 * 7), 进一步分解的最大值(比如:3 * dp[7]))

这个方法在time complexity上,在目前的时间点上faster than 52.24%

//1ms
    public int integerBreak(int n) {
		if (n <= 3) {
			return (n - 1);
		}
		
		int[] dp = new int[n + 1];
		dp[2] = 1;
		dp[3] = 2;
		
		for (int i = 4; i <= n; i++) {
			for (int j = 1; j <= i; j++) {
			  //每个i对应很多j,要把dp[i]也放入max的比较中,防止最大值被淹没
			  //可以是j*(i-j),也可以是(i-j)进一步拆分的数字的乘积*i
				dp[i] = Math.max(dp[i], j * (i - j));
				dp[i] = Math.max(dp[i], j * dp[i - j]);
			}
		}
		
		return dp[n];
    }

(2) 数学方法
参照https://blog.youkuaiyun.com/qq_17550379/article/details/82811007
以3作基底的乘积最大,推导
我们将n拆分成n/x个数值为x的整数,那么这些整数的乘积就是xn/xx^{n/x}xn/x, 这个乘积对x求导
y=xn/xy = x^{n/x}y=xn/x
lny=(n/x)lnxlny = (n/x)lnxlny=(n/x)lnx
y′/y=−(n/x2)lnx+(n/x2)y'/y = -(n/x^{2})lnx + (n/x^{2})y/y=(n/x2)lnx+(n/x2)
y′=n(1−lnx)x(n/x−2)y' = n(1-lnx)x^{(n/x - 2)}y=n(1lnx)x(n/x2)

所以在x=e的时候乘积最大,x=2或3
2∗2∗2<3∗32*2*2 < 3*3222<33
所以想要乘积最大,那么一定要将3作为基底,并且<=4的余数不再进行拆分。

此方法在当前时间点上,time complexity: faster than 100%

//0ms
    public int integerBreak(int n) {
        if (n <= 3) {
            return (n - 1);
        }
        
        int result = 1;
        
        //<=4的余数不再拆分
        while (n > 4) {
            result *= 3;
            n -= 3;
        }
        
        result *= n;
        
        return result;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值