题目描述:剪绳子_牛客网
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m]。请问k[0]xk[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
解法(1):空间O(n),时间O(n^2)。
动态规划。解法(1)(2)的区别是要不要把2和3的值单独讨论,分别得出不同的公式。
# -*- coding:utf-8 -*-
class Solution:
def cutRope(self, number):
# write code here
if number<=1:
return 0
f = [0, 1]
for i in range(2, number+1):
mul = 0
for j in range(1, (i>>1)+1):
res = i-j
mul = max(max(j, f[j])*max(res, f[res]), mul)
f.append(mul)
return f[-1]
解法(2):空间O(n),时间O(n^2)。
动态规划。当n≥4时,可以将解法(1)的公式简化如下;n<4时要单独讨论。
# -*- coding:utf-8 -*-
class Solution:
def cutRope(self, number):
# write code here
if number<2:
return 0
if number==2:
return 1
if number==3:
return 2
d = [0, 1, 2, 3]
for i in range(4, number+1):
d.append(max([d[j]*d[i-j] for j in range(1, (i>>1)+1)]))
return d[-1]
解法(3):空间O(1),时间O(1)。
贪婪算法。当n>=5时,把绳子尽量剪成每段长度为3。当n==4,剪成2*2或者不剪。
推导:首先看n<10时的划分情况,可以看出每刀按3剪的规律。
n>=10时,总会再细分到剪为个位数的情况,因此可证得该归纳规律。
# -*- coding:utf-8 -*-
class Solution:
def cutRope(self, number):
# write code here
if number<2:
return 0
if number==2:
return 1
if number==3:
return 2
if number%3==1:
return (3**(number//3-1))*4
if number%3==2:
return (3**(number//3))*2
return 3**(number//3)