原题链接
题目描述:
方法一:利用数学公式推导
根据题意,任意一段长为n绳子都可以细分为a段( n = n 1 + n 2 + n 3 + . . . + n a n=n_1+n_2+n_3+...+n_a n=n1+n2+n3+...+na);
要使 S = n 1 × n 2 × n 3 × . . . × n a S=n_1\times n_2\times n_3\times...\times n_a S=n1×n2×n3×...×na值最大,由下面式子:
n 1 + n 2 + n 3 + . . . + n a a > = n 1 n 2 n 3 . . . n a a \frac{n_1+n_2+n_3+...+n_a}{a}>=\sqrt[a]{n_1n_2n_3...n_a} an1+n2+n3+...+na>=an1n2n3...na
得出当且仅当 n 1 = n 2 = n 3 = . . . = n a n_1=n_2=n_3=...=n_a n1=n2=n3=...=na时等号才成立,意思就是当把长度为N的绳子细分成数段等长为 x 的绳子时,他们的乘积 S S S 取得最大值,且乘积值为 x a x^a xa
由此我们就将问题转化为求解每段绳子长度x为何值时, S S S才能取得最大值
要求 S = x a S=x^a S=xa的最大值,我们需要对式子稍微变换一下;
由 a = n x a=\frac{n}{x} a=xn,得: S = x n x S=x^{\frac{n}{x}} S=xxn对两边取 l n ln ln得: l n S = n x l n x lnS=\frac{n}{x}lnx lnS=xnlnx
两边同时对x求导,得 1 S S ′ = − n x 2 l n x + 1 x × n x = ( 1 − l n x ) × n x 2 \frac{1}{S}S'=-\frac{n}{x^2}lnx+\frac{1}{x}\times \frac{n}{x}=(1-lnx)\times \frac{n}{x^2} S1S′=−x2nlnx+x1×xn=(1−lnx)×x2n
令 S ′ = 0 S'=0 S′=0时, 1 − l n x = 0 1-lnx=0 1−lnx=0,解得 x = e x=e x=e
S = { 大 于 0 , x ∈ ( 0 , e ) 小 于 0 , x ∈ ( e , + ∞ ) S=\begin{cases} 大于0, x\in(0 , e)\\ 小于0,x\in(e,+\infty)\\ \end{cases} S={大于0,x∈(0,e)小于0,x∈(e,+∞)
因为 x x x为正整数,当 S S S值为最大时, x x x的可能取值有2或者3;
当 x = 2 x=2 x=2时, S ( 2 ) = 2 n 2 S(2)=2^\frac{n}{2} S(2)=22n
当 x = 3 x=3 x=3时, S ( 3 ) = 3 n 3 S(3)=3^\frac{n}{3} S(3)=33n
上面两个等式右边式子同时取6次方,不难判断出 S ( 3 ) = 9 n > S ( 2 ) = 8 n ( n 是 正 整 数 ) S(3)=9^n>S(2)=8^n(n是正整数) S(3)=9n>S(2)=8n(n是正整数)
所以我们可以得出结论:
只有尽可能地将绳子等分为多段长度为3的绳子,它们长度的乘积 S S S才能取得最大
这种剪法可能有三种情况:
第一种:
n刚好能被3整除,则此时乘积 S = 3 a S=3^a S=3a
第二种:
n除以3之后,余下一段长度为1的绳子,此时我们应该分出一段长度为3的绳子与余下的长度为1的绳子重新拼接回来,拼接后的绳子长度为4,则
S = 3 a − 1 × 4 S=3^{a-1}\times4 S=3a−1×4第三种:
n除以3之后,余下一段长度为2的绳子,则余下的绳子不必再剪,所有绳子的乘积为 S = 3 a × 2 S=3^a\times2 S=3a×2
以上内容参考原文
代码的实现如下:
/*
执行用时:0 ms
内存消耗:6 MB
*/
class Solution {
public:
int cuttingRope(int n) {
if(n<4)
return n-1;
else
{
int a=n/3;//记录倍数
int b=n%3;//记录余数
if(b==0)
return pow(3,a);
else if(b==1)
return pow(3,a-1)*4;
else
return pow(3,a)*2;
}
}
};
方法二:动态规划法
//用时0ms,空间:5.9MB
class Solution {
public:
int cuttingRope(int n) {
int a[59] = { 0 };
if (n < 4)
return n - 1;
for (int i = 1; i <= n; i++)
{
a[i] = i;//初始为原长
for (int j = 1; j < i; j++)
a[i] = max(a[i], a[i - j] * a[j]);//比较减j时,与不减时的乘积大小,保留最大值
}
return a[n];
}
};
更多算法题解,更关注我个人微信公众号:艺千秋录