LeetCode_343:數字劃分問題(遞歸+動態+數學)

題目描述

原題地址:https://leetcode-cn.com/problems/integer-break/
給定一個正整數 n,將其拆分為至少兩個正整數的和,并使這些整數的乘積最大化。 返回你可以獲得的最大乘積。

示例 1:

輸入: 2
輸出: 1
解釋: 2 = 1 + 1, 1 × 1 = 1。

示例 2:

輸入: 10
輸出: 36
解釋: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。

說明: 你可以假設 n 不小于 2 且不大于 58。

解法1——遞歸

遞歸的思路無非就是自頂向上,很容易想出來,代碼如下

//遞歸-自頂向下
public static int integerBreak(int n) {
    return dfs(n);
}

public static int dfs(int n){
    if(n == 1 || n == 2){
        return 1;
    }
    int res = 0;
    for(int i = 1;i < n;i++){
        res = Math.max(res,Math.max(i * dfs(n - i),i * (n - i)));
    }
    return res;
}

這種方法雖然比較容易想出來,但是中間重復計算的非常多,實際在LeetCode中不能AC

解法2——動態規劃

動態規劃那么就是自底向上的方法,根據上一步的遞歸,狀態轉移方程為
dp[i] = \max(dp[i],\max(j*dp[i-j],j*(i-j)))
其中,j為區間[1,i-1]之間的數。

//動態規劃-自下向上
public static int integerBreak2(int n) {
    int[] dp = new int[n + 1];
    dp[2] = 1;
    for(int i = 2;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)));
        }
    }
    return dp[n];
}

解法3——數學分析

根據高中學習的均值不等式,可以得到
n= \frac{a_1+a_2+...+a_m}{m} \ge \sqrt[m]{a_1a_2...a_m}
a_1=a_2=...=a_m=x,那么目標積為
f(x)=x^{ \frac{m}{x}}
對上述函數求導數,可以得到
f'(x)=m(1- \ln{x})x^{ \frac{n}{x}-2}
x=e=2.71828...時取得最大值,那么離e最近的兩個整數為23,下面再來考慮時選擇3還是選擇2。

假設一個數n=3x+2y,則乘積為f=3^x2^y=3^x2^{ \frac{n-3x}{2}},對其兩邊取對數可以得到
\ln f=x \ln{3}+\frac{n-3x}{2} \ln{2}=(\ln{3}-\frac{3}{2}\ln{2})x+\frac{n}{2}\ln{2}
由于(\ln{3}-\frac{3}{2}\ln{2}) > 0,所以是x越大越好,所以應該盡可能的多取3.


//數學方法
public static int integerBreak3(int n){
    if(n == 2){
        return 1;
    }
    if(n == 3){
        return 2;
    }
    int res = 1;
    while(n > 4){
        res *= 3;
        n -= 3;
    }
    return res * n;
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • LeetCode 刷題隨手記 - 第一部分 前 256 題(非會員),僅算法題,的吐槽 https://leetc...
    蕾娜漢默閱讀 17,909評論 2 36
  • 數組 記錄《劍指offer》中所有關于數組的題目,以及LeetCode中的相似題目 相關題目列表 說明 由于簡書...
    wenmingxing閱讀 1,530評論 1 12
  • 原文歡迎關注http://blackblog.tech/2018/06/03/LeetCodeReview/歡迎關...
    BlackBlog__閱讀 1,972評論 0 9
  • 前言 2. 實現 Singleton 3. 數組中重復的數字 4. 二維數組中的查找 5. 替換空格 6. 從尾到...
    Observer_____閱讀 2,975評論 0 1
  • 本文內容為練習LeetCode題目時的解題思路和不同算法的記錄,實現語言為C++,代碼保存在Github,均已在L...
    SK木眠閱讀 1,020評論 0 0