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;
		
		
	}

}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章