leetcode 343. Integer Break(从递归到动态规划)

题目;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];
	}
点赞