由题知,\(n=n_1+...+n_m\),我们要求\(max(n_1\cdot n_2\cdot ... \cdot n_m)\),由算术几何均值不等式\(\frac{n_1 + n_2+...+n_m}{m}\geq \sqrt[m]{n_1n_2...n_m}\),等号在\(n_1=n_2=...=n_m\)处取得,所以当绳子均分时得到乘积最大,我们设每段长x,则有\(n=mx\),乘积为\(x^m\),令\(y=x^m=x^{\frac{n}{x}}=(x^{\frac{1}{x})^n}\),求此时的最大值等价于求\(y=x^{\frac{1}{x}}\)的最大值,两边取对数求导,
\[lny=\frac{1}{x}lnx\\ \frac{y'}{y}=\frac{1-lnx}{x^2}\\ y'=x^{\frac{1}{x}}\cdot \frac{1-lnx}{x^2} \]令\(y'=0\),可得\(x=e\),当\(x<e\)时,\(y'>0\),函数递增;当\(x>e\)时,\(y'<0\),函数递减,\(x=e\)为极大值点。
因为x要取整数,所以x需要在2和3之间选一个,比较\(2^\frac{1}{2}\)和\(3^\frac{1}{3}\),同时乘六次方得\(2^3<3^2\),所以x取3时,函数值更大。
时间:\(O(N)\)
空间:\(O(1)\)
class Solution: def cuttingRope(self, n: int) -> int: # K神源码,时间O(1),空间O(1) if n <= 3: return n - 1 a, b = n // 3, n % 3 if b == 0: return int(math.pow(3, a)) if b == 1: return int(math.pow(3, a - 1) * 4) return int(math.pow(3, a) * 2) # 参考自郁郁雨 if n < 4: return n - 1 res = 1 while n > 4: res *= 3 n -= 3 return res * n
设置dp数组保存长度为0~n的最终结果,外循环代表绳子的长度,内循环代表最后一刀截的长度,如果为1则对乘积无影响,所以从2开始,截一刀之后需要看当前长度乘剩下的长度(未切)的乘积与当前长度乘剩下长度(切过)最大值的乘积的大小,然后再与完全不剪dp[i]作比较。
class Solution: def cuttingRope(self, n: int) -> int: dp = [0] * (n + 1) dp[2] = 1 for i in range(3, n + 1): for j in range(2, i): dp[i] = max(dp[i], max(j * (i-j), j * dp[i-j])) return dp[n]