343.Integer Break---dp
题目链接:https://leetcode.com/problems/integer-break/description/
题目大意:给定一个自然数,将其分解,对其分解的数作乘积,找出最大的乘积结果。例子如下:
法一(借鉴):dp,一维dp,dp[i]表示i的最大分解结果的乘积,而dp[5]可以dp[4],dp[3],dp[2],dp[1]为基础,dp[4]可以dp[3],dp[2],dp[1]为基础,代码如下(耗时1ms):
1 //dp[i]表示给定i分解后能得到的最大乘积值 2 public int integerBreak(int n) { 3 int dp[] = new int[n + 1]; 4 dp[1] = 1; 5 dp[2] = 1; 6 for(int i = 3; i <= n; i++) { 7 for(int j = 1; j <= i / 2; j++) { 8 //max里面要加上dp[i],因为里层for循环会不断更新dp[i],否则dp[i]得到就是最后一次的计算结果,而取不到最大值 9 //后面Math.max(j, dp[j]) * Math.max(i - j, dp[i - j]),因为j+(i-j)=i,所以计算j和i-j的乘积,是正常的,只不过这里可以用到先前已经算过的dp[j]和dp[i-j],因为dp[j]的结果就是j的最大分解结果,那么也可以是i的分解结果 10 dp[i] = Math.max(dp[i], Math.max(j, dp[j]) * Math.max(i - j, dp[i - j])); 11 } 12 } 13 return dp[n]; 14 }
法二(借鉴):数学方法,数学原理:https://leetcode.com/problems/integer-break/discuss/80721/Why-factor-2-or-3-The-math-behind-this-problem.,由数学知,一个整数分解,当分解成相同的数时,乘积最大,而由于给定的自然数不一定都能分解成相同的数,所以又由数学知,求导办法见https://www.cnblogs.com/zywscq/p/5415303.html,当分解得到的数越靠近e,得到的乘积值越大,那么也就是能取3则取3,不能则取2。而又如6=2+2+2=3+3,又2*2*2<3*3,所以当能分解成3个2时,应该换算成2个3,所以下面与3求余,然后分情况分解。代码如下(耗时0):
1 public int integerBreak(int n) { 2 if(n == 2) { 3 return 1; 4 } 5 else if(n == 3) { 6 return 2; 7 } 8 else if(n == 1) { 9 return 1; 10 } 11 else if(n % 3 == 0) { 12 return (int)Math.pow(3, n / 3); 13 } 14 else if(n % 3 == 1) { 15 return 2 * 2 * (int)Math.pow(3, (n - 4) / 3); 16 } 17 else { 18 return 2 * (int)Math.pow(3, (n - 2) / 3); 19 } 20 }