题目;Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get.
Input: 2
Output: 1
Explanation: 2 = 1 + 1, 1 × 1 = 1.
题意:将一个数分割成若干个正整数的和,求这若干个正整数乘积最大值。
算法思路1:自顶向下,纯递归的思路,要算f(n)(该方法的返回值表示 n 分割成若干个正整数乘积最大值),分割的第一个数可以为1,2,…,(n-1),故有n种法,这n种分法的最大值即为答案。(max,i * (n-i),i * f(n-i)),max记录了前面分割的最大值,i * (n-i)表示分割成2个数,i * (f(n-i))表示 i 乘以一个f(n-i),一定要明确f(n)的含义。该算法显然是通不过的,因为它有大量的重复计算,先把代码附上,接下来在此基础上进行改进。
public int integerBreak(int n) {
int max = -1;
for(int i=1;i<=n-1;i++){
max = max(max,i*(n-i),i*integerBreak(n-i));
}
return max;
}
int max(int a,int b,int c){
return Math.max(Math.max(a, b), c);
}
算法思路2:自顶向下,记忆搜索,用一个数组存储得到的结果,当需要该结果时,直接拿来用就好,就不用计算了,这节省了大量时间。
int[] memo;
public int integerBreak(int n) {
memo = new int[n+1];
for(int i=0;i<=n;i++)
memo[i] = -1;
return integerBreakson(n);
}
public int integerBreakson(int n){
int max = -1;
if(memo[n]!=-1)
return memo[n];
for(int i=1;i<=n-1;i++){
max = max(max,i*(n-i),i*integerBreakson(n-i));
}
memo[n] = max;
return max;
}
int max(int a,int b,int c){
return Math.max(Math.max(a, b), c);
}
算法思路3:自下向上,动态规划,要解决f(n),得先解决f(1),f(2)等等,将解决得到的结果放进memo数组中,不断用前面得到的结果递推后面的问题,如此往复,即可求出f(n)。
static int max(int a,int b,int c){
return Math.max(Math.max(a, b), c);
}
//leetcode 343. Integer Break 自下向上,动态规划
static int[] memo;
public static int integerBreak(int n) {
memo = new int[n+1];
for(int i=0;i<=n;i++)
memo[i] = -1;
memo[1] = 1;
for (int i = 2; i <= n; i++) {
int max2 = -1;
for (int j = 1; j <= i - 1; j++) {
max2 = max(max2, j * (i - j), j * memo[i - j]);
}
memo[i] = max2;
}
return memo[n];
}