剑指offer 14-1 剪绳子
题目描述:
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
思路:动态规划
设置一个数组保存每个长度对应的结果.
长的绳子可以分解短的绳子,即大问题分解为小问题.
实现一:
dn[i]保存每个长度对应的最大乘积.
转移方程:dn[i] = max(dn[i], j * (i - j), j * dn[i - j]).
最基本的是剪成两段 j * (i - 1).
或者剪成 j * dn[i - j], dn[i -j]包含之前剪多次的结果,例如 dn[i - j] 剪两刀,如果 dn[i] 更新为j * dn[i - j],dn[i]剪了3刀.
class Solution:
def cuttingRope(self, n: int) -> int:
dn = [0]*(n + 1)
for i in range(n + 1):
for j in range(0, i):
dn[i] = max(dn[i], j * (i - j), j * dn[i - j])
return dn[n]
实现二:
先初始化前几个,然后递推.
class Solution:
def cuttingRope(self, n: int) -> int:
if n == 2 : return 1 #据题意,总长度为2还是要剪一刀
elif n == 3 : return 2
else:
dn = [0] * (n + 1)
dn[0] = 0
dn[1] = 1
dn[2] = 2
dn[3] = 3 #长度剩下1~3时都不剪了
for i in range(4,n + 1):
dn[i] = 0
for j in range(1, i):
temp = j * dn[i-j]
if temp > dn[i]:
dn[i] = temp
return dn[n]