1. 程式人生 > 其它 >343.整數拆分

343.整數拆分

目錄

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。

題解

m*(n-m) 就保證了和為i,並且計算乘積進行比較。
m從1取到n-1,取到i的話有個乘數就為0,結果就是0,是最小的乘積。
但是拆分的個數是不確定的。假設n=10,3*7=21,這裡就把7又看成一個新的m*(n-m)

,也就是把7繼續拆,這裡就大數拆小數,需要用到之前的狀態,那麼可以試試動態規劃。

所以拆法有這兩種那麼我們選擇哪種?題目是求最大乘積,誰大選誰

1.確定dp陣列以及下標的含義
dp[i] 表示i的最大乘積

2.確定遞推公式
dp[i] = Math.max(j*(i-j),j*dp[i-j])
需要注意的是j是從1取到i-1,那麼j應該屬於內迴圈,j在變化的時候還應該比較之前dp[i]和現在新的j產生的最大乘積之間的大小

dp[i] =Math.max(Math.max(j*(i-j),j*dp[i-j]))

3.dp陣列如何初始化
dp[0] = 0
dp[1] = 0 dp[0]和dp[1]其實沒有意義的
dp[2] = 1
n從2開始

4.確定遍歷順序
要利用之前的資料,應該從左到右遍歷

程式碼

class Solution {
    public int integerBreak(int n) {
        int [] dp = new int [n+1];
        dp[2] = 1;
        for(int i=3;i<n+1;i++){
            for(int j=1;j<=((i+1)/2);j++){  //由於對稱性 2*3 和3*2 是一樣的
                dp[i] = Math.max(dp[i],Math.max(j*(i-j),j*dp[i-j]));
            }
        }
        return dp[n];
    }
}