343-Integer-Break

原题链接

0x0 题目详情

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

测试用例:

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

示例 2: 输入: 10 输出: 36 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。

说明: 你可以假设 n 不小于 2 且不大于 58。

0x1 解题思路

这道题虽然打着动态规划的标签,但实际上用数学方法更快。

数学方法:

对于一个数num=x+y拆成两个整数的话,xy的差值越小xy的乘积才会越大。例如增大xy的差值(假设x>=y)。num=(x+1)+(y-1),(x+1)*(y-1)=xy-(x-y)-1<xy。所以如果要把一个数拆成两个两个整数,那么这两个数的差值越小越小,最好是x==y

那么把一个数拆成n个整数的是一样的,最好的情况是这n个数相等。

那么最完美的情况就是每个拆分后的数为(n/x)。最后的乘积为(n/x)^n。对该函数求导,当x=n/e时乘积最大。那么每段的长度为e时,乘积最大。离e最近的整数为3。所以我们需要把数n拆成尽可能多的3。

但是上述规则只适用于n>=4,当n<=4时,拆分后的最大乘积为(n-1)。

暴力递归方法:

对于一个数n我们可以拆成两部分xy。我们可以选择拆分或者不拆分x或者y。那么拆分后的最大乘积就会有四种情况(假设x拆分后的最大乘积为left,y拆分后的最大乘积为right):

  • x*y

  • x*right

  • left*right

  • left*y

最后拆分后的最大值在这四者中选一个最大的。

那么对于数n,我们有n-1个拆分点。又是拆分点,跟字符串的dp有点像了奥。

0x2 代码实现

数学方法:

递归方法:

动态规划:

0x3 课后总结

拆分整数、割绳子都是一类问题。

Last updated

Was this helpful?