题目描述:
法 0 : 穷举……
题目只要求2 - 58 的正整数,依次根据测试用例返回表就行了……
法 1 : 动态规划
分析: 1 不可拆,2只能拆成1*1,对大于2 的数字 n ,可以:
①拆成两个数: i 和 n - i ,将 n - i 继续拆下去,即:dp[ n ] = i * dp[ n - i ] ;
②拆成两个数: i 和 n - i ,到此为止不再拆分,则有: dp[ n ] = i * ( n - i );
n处的dp值取二者间最大即可。 其中, i 是 2 或 3 ;理论上说,i 应该从 2 试到 n - 2,但是,经证明,若将 i 拆为 4 或以上的整数,其结果将小于等于拆为 2 或 3 之后递归计算的结果,力扣官方给的证明比较清晰,这里不再赘述,只是讨论一点我的个人看法:
将 n (n>=4) 拆为 k 和 n-k, 其乘积为 ,
而对于方程: ,其最大值在 处取到。
故②式有最大值 ,故由“dp[n]代表第n项之前乘积最大值”定义,对①式, 一定有,而在 处并未取到极大值,其极大值在处取到,即如果当,一定有,解得 n = 8,即:
若n=8,此时一定有 dp[ n ] = i * dp[ n - i ] ;
若n < 8,一定有 dp[ n ] = i * ( n - i ) ;表现为
即:对于>=8的整数,一定可以递归分解为 2 - 7 各数的dp之积,而 2 - 7 的 dp值因子只有 2 和 3 ,故:对于>=8的整数,一定分解为2的幂与3的幂之积,且有 dp[ n ] 的定义保证其最大。
法 3 : 纯数学
根据柯西不等式,数总和一定时,当各个因子相等,所得到的乘积最大。
故可以构建函数:,其中 x 为要分解为x个因子,每个因子大小为,y代表最终结果,求导得在处,y有最大值(不会求导取两边对数再导)。故要分解成个因子,每个因子均为e。在整数域,只能取或。而(两边同时6次方)。即 n 要不断分解为 3 的和。
关键在于:分解到最后势必出现余数分别为0,1,2的三种情况;
①余0,说明是3的整数次幂,刚好最大;
②余1,说明 , 而 4 是特例,拆成2*2最佳,而非3*1。故这里拆成 ,此时达到最大;
③余2,直接乘上去即可保证最大,因为即便拆出来5最后也是2*3。
代码如下:
int integerBreak(int n) {
if(n<4) return n-1;// 2 和 3 的最大乘积分别是 1 和 2
int sum=1;
while(n>4)
{
n-=3;
sum*=3;
}
//退出循环时,n只可能为2,3,4,都可直接作为因子
return sum*n; //n=4直接返回4
}
总结:
dp是空间换时间,数学推导或许是拿脑子换时间空间?