dp:LeetCode:343:整数拆分:用算术集合均值不等式、暴力搜索、备忘录数组、动态递归

整数拆分

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。
示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
说明: 你可以假设 n 不小于 2 且不大于 58。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/integer-break
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

用算术集合均值不等式

package dp;

import java.util.Scanner;

public class 整数拆分 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		//算术几何均值不等式,等号当且仅当n1=n2=``na
		//推论以,若拆分的数量a确定,则各拆分数字相等时,乘积最大
		//将数字n尽可能以因子3等分时,乘积最大
		if(n<=3){
			System.out.println(n-1);
			return;
		}
		int a=n/3;//整数部分
		int b=n%3;//余数部分
		if(b==0){
			System.out.println((int)Math.pow(3,a));
			return;
		}
		if(b==1){
			//若余数为1,应该把3+1替换位2+2,因为2*2>3*1
			System.out.println((int)Math.pow(3,a-1)*4);
			return;
		}
		//余数为2,则不再拆分,2>1*1
		System.out.println((int)Math.pow(3, a)*2);
	}

}

动态递归:

package dp;

import java.lang.reflect.Array;
import java.util.Scanner;

public class 整数拆分动态规划 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int[] dp=new int[n+1];
		//状态数组dp[i]表示数字i拆分为至少两个正整数之和的最大乘积。,为了方便计算,dp的长度是n+1,值初始化为1
		//显然dp[2]等1,外层循环从3开始遍历,一直到n停止,内层循环j从1开始遍历,一直到i之前停止,代表数字i可以拆分位j+(i-j_
		//但j*(i-j)不一定是最大的乘积,因为i-j不一定大于dp[i-j]数字i-j拆分成整数之和的最大乘积,这里要选择最大值作为dp[i]的结果
		//空间复杂度是 O(N)O(N),时间复杂度是 O(N^2)O(N^2)
		dp[2]=1;
		for(int i=3;i<=n;i++){
			for(int j=1;j<=i-1;j++){
				dp[i]=Math.max(dp[i],Math.max(j*dp[i-j],j*(i-j)));
			}
		}
		System.out.println(dp[n]);
	}

}

暴力搜索

在这里插入图片描述
上述表达式是表明n - i需要继续分解的情况,但如果n - i比F(n - i)要大,显然就不用再继续分解了。故我们还需要比较i * (n - i)与i * F(n - i)的大小关系。所以完整的表达式应该为:

作者:97wgl
链接:https://leetcode-cn.com/problems/integer-break/solution/bao-li-sou-suo-ji-yi-hua-sou-suo-dong-tai-gui-hua-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在这里插入图片描述

package dp;

import java.util.Scanner;

public class 整数拆分暴力解法 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		System.out.println(integerBreak(n));
	}
	public static int integerBreak(int n){
		if(n==2){
			return 1;
		}
		int res=-1;
		for(int i=1;i<=n;i++){
			res=Math.max(res,Math.max(i*(n-i),i*integerBreak(n-i)));
		}
		return res;
	}

}

记忆化数组

在这里插入图片描述

package dp;

import java.util.Scanner;

public class 整数拆分记忆化搜索 {

	private static int[] memory;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		memory = new int[n+1];
		System.out.println(integerBreakHelper(n));
	}
	public static int integerBreakHelper(int n){
		if(n==2)
			return 1;
		//memory的初值位0,如果它不为0,说明已经计算过了,直接返回即可
		if(memory[n]!=0)
			return memory[n];
		int res=-1;
		for(int i=1;i<=n-i;i++)
			res=Math.max(res, Math.max(i*integerBreakHelper(n-i), i*(n-i)));
		//把每次的结果保存到备忘录数组中
		memory[n]=res;
		return res;
		
		
	}

}

在这里插入图片描述

发布了342 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44522477/article/details/105572958