Leet343.整數拆分(Integer Break)

/*
 * P96面試題14:剪繩子
 * 給定一個正整數 n,將其拆分爲至少兩個正整數的和,並使這些整數的乘積最大化。 返回你可以獲得的最大乘積
 */
public class T14
{
	/*
	 * 解法一:動態規劃
	 * 令dp[n]爲n對應的最大乘積
	 * 維護這個最優解數組
	 * 註釋中的寫法是另一種理解方式
	 * 當拆分出的一部分的長度爲4時 這一段是否需要再進行拆分?
	 * 4=2*2 而小於4時 例如3 若拆分3 則得到1*2=2 結果將小於不拆分的結果
	 * 而當大於4時 例如5 拆分爲2*3=6 >5 所以4爲分界點
	 * 大於4的部分需要再進行拆分 小於4的部分則不需要拆分
	 * 此方法的時間複雜度爲O(n^2)
	 */
	public static int integerBreak(int n)
	{
		int dp[]=new int[n+1];
		dp[1]=1;
		for(int i=2;i<=n;i++)
		{
			for(int j=1;j<i;j++)
			{
				dp[i]=Math.max(dp[i], (i-j)*Math.max(dp[j], j));
			}
		}
		return dp[n];
		
//		int dp[]=new int[n+1];
//		dp[1]=1;
//		for(int i=2;i<=n;i++)
//		{
//			for(int j=1;j<i;j++)
//			{
//				if(j<=4)
//				{
//					dp[i]=Math.max(dp[i], (i-j)*j);
//				}
//				else
//				{
//					dp[i]=Math.max(dp[i],(i-j)*dp[j]);
//				}
//			}
//		}
//		return dp[n];
	}
	
	/*
	 * 解法二:貪心
	 * 首先由均值不等式中的算數平均數>=幾何平均數可知
	 * 將輸入的n拆分成多個相等的數時積最大
	 * 先假設最優拆法所拆出的每一個數都爲x
	 * 那麼一共會拆出n/x個數
	 * 設他們的積爲f(x) 則f(x)=x^(n/x)
	 * 爲了求f(x)的最大值 可以對其求導
	 * 過程省略
	 * 最終有 x=e時f(x)有極大值
	 * e=2.7 故優先拆成3 拆不成3則拆2
	 * 實際上當剩餘長度小於等於4時
	 * 剩餘部分不拆分即可(方法一中說明)
	 * 此方法的時間複雜度爲O(lgn)
	 */
	public static int integerBreak2(int n)
	{
		if (n < 2)
	        return 0;
	    if (n == 2)
	        return 1;
	    if (n == 3)
	        return 2;
	    int timesOf3=0;
	    while(n>3)
	    {
	    	if(n<=4)
	    		break;
	    	timesOf3++;
	    	n-=3;
	    }
	    return (int)(Math.pow(3, timesOf3))*(n);
	}
	
	/*
	 * 記錄一下另一種看到的思路
	 *
	 * class Solution {
public:
    int integerBreak(int n) {
      if(n==2){return 1;}
      if(n==3){return 2;}
      n-=2;
      return pow(3,n/3)*(n%3+2);
    }
};

	 */
}

 

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