343. Integer Break
好吧我还是把题目贴出来,反正不长:
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.
For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).
Note: You may assume that n is not less than 2 and not larger than 58.
又是一个要 靠罗列来发现规律 的例子:
规模n | 最大值 |
---|---|
2 | 1*1 |
3 | 2*1 |
4 | 2*2 |
5 | 3*2 |
6 | 3*3 |
7 | 3*2*2 |
8 | 3*3*2 |
9 | 3*3*3 |
10 | 3*3*2*2 |
11 | 3*3*3*2 |
12 | 3*3*3*3 |
好,我们定义一个最大值数组
dp[n]
(dynamic programming),dp[5]
即规模为5时候的最大值。
从上面的表中,你发现了什么规律?
尽可能避免拆成1
规模为4的时候,恰好
dp[4]=4
,之后dp[5]
就开始>5了,而之前的dp[2]、dp[3]
都是小于自身规模(n=2,n=3)的。如果我们把2到6看成基本集合,那么后面从7开始是可以归因到2到6的,首先归因到6肯定不对,我们不欢迎1的拆分除非迫不得已(2和3只能那样拆才能拆成2个数的乘积啊),比如7可以写成
2*dp[5]=2*3*2
,也可以写成3*dp[4]=3*2*2
,但是没必要写成4*dp[3]
了,因为dp[3]
已经小于3了,也就是说,我们每次归因都到dp[4]
打止。但这还是不对,我们看9,9可以归因为2*dp[7],3*dp[6],4*dp[5],5*dp[4]
(这可不行啊,5已经小于dp[5]
了,所以完全不能用,之后的什么6啊,7啊更加不能用,所以其实也是到4打止了,不再往前搜),所以实际上我们最多往前归因4位。其实这还是不对,聪明的你应该已经发现,往前归因4位,其实跟归因2位两次是一样的。所以我们只需从2*dp[n-2],3*dp[n-3]
中选出大者就行。我们得到动态规划公式(动态规划就是归因(多元因)啊,而递归则是单一因):
dp[n]=max(2*dp[n-2],3*dp[n-3])
,且n>=7(因为我们不越过dp[4]
啊)。
代码如下:
class Solution(object):
def integerBreak(self, n):
"""
:type n: int
:rtype: int
"""
dp = [0]*(n+7)
dp[2]=1
dp[3]=2
dp[4]=4
dp[5]=6
dp[6]=9
if(n>=7):
for x in range(7, n + 1):
dp[x] = max(3 * dp[x - 3], 2 * dp[x - 2])
return dp[n]
我自己感到这代码有着深深的蛋疼(手动赋了一大堆值),因为我看到别人是这样写的:
class Solution(object):
def integerBreak(self, n):
"""
:type n: int
:rtype: int
"""
if n<4:
return n-1
dp = [0]*(n+1)
dp[2], dp[3] = 2, 3
for x in range(4, n + 1):
dp[x] = max(3 * dp[x - 3], 2 * dp[x - 2])
return dp[n]
好吧,他的代码其实也差不多。
下面真正吊炸天的来了。
聪明的你肯定已经发现,这完全就是个2跟3的游戏,是的,事实就是如此。
n%3==0时,就全部用3
n%3==2时,勉为其难用个2吧
n%3==1时,就再勉为其难用两个2吧
当n%3==3,哈哈别傻了,
当然你还得看到,最开始的2个里面是有1的,可不要忘了。
所以,得到牛逼的专门解题代码:
class Solution(object):
def integerBreak(self, n):
"""
:type n: int
:rtype: int
"""
if n < 4:
return n - 1
if n % 3 == 0:
return 3 ** (n / 3)
if n % 3 == 1:
return 3 ** ((n - 3) / 3) * 4
if n % 3 == 2:
return 3 ** ((n - 2) / 3) * 2
这种题也就娱乐娱乐,程序员还是要以工程代码为主业啊。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。