1、剪绳子
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],...,k[m]。请问k[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
方案一:递归
我们先定义函数f(n)为把绳子剪成若干段之后的各段长度乘积的最大值。在剪第一刀的时候,我们会有n-1种可能的选择,也就是说剪出来的第一段绳子的长度可能为1,2,......n-1。
因此就有了递归公式 f(n) = max(f(i)*f(n-i)),其中0<i<n.
#递归写法
class Solution:
def cutRope(self, number):
# write code here
if number < 2:
return 0
if number == 2:
return 1
if number == 3:
return 2
return self.cutRopeCore(number)
def cutRopeCore(self, number):
if number < 4:
return number
max_ = 0
for i in range(1, number/2+1):
max_ = max(self.cutRopeCore(i) * self.cutRopeCore(number - i), max_)
return max_
递归会产生大量不必要的重复计算,所以可以考虑采用动态规划的方法
方案二:贪婪
尽量把大于5的数分解成3的乘积,如果剩下的长度为4,则把4分解成2和2,因为3x1 < 2x2。
#贪婪算法
class Solution:
def cutRope(self, number):
# write code here
if number < 2:
return 0
if number == 2:
return 1
if number == 3:
return 2
#申请辅助空间
timesOf3 = number / 3
if (number - timesOf3*3) == 1:
timesOf3 -= 1
timesOf2 = (number - timesOf3*3) / 2
return pow(3, timesOf3)*pow(2, timesOf2)
方案三:动态规划
从下而上的计算,即先求的f(2),f(3),再计算得到f(4),f(5),以此往后,直到f(n)
#递归写法
class Solution:
def cutRope(self, number):
# write code here
if number < 2:
return 0
if number == 2:
return 1
if number == 3:
return 2
products = [0]*(number+1)
products[0] = 0
products[1] = 1
products[2] = 2
products[3] = 3
#动态规划
for i in range(4,number+1):
max_ = 0
for j in range(1, i/2+1):
max_ = max(products[j]*products[i-j], max_)
products[i] = max_
return products[number]