1. 程式人生 > 實用技巧 >LeetCode 343 整數拆分

LeetCode 343 整數拆分

LeetCode 343 整數拆分

給定一個正整數,將其拆分為至少2個正整數之和,求出拆分後所有數的最大乘積

  1. 遞迴(暴力),對於數n,每次將其拆分為兩個數:curr(本次拆分值)、rem(剩餘值),並遞迴呼叫對rem繼續拆分直到為0、1
  2. 記憶化遞迴,將對每次rem的最優拆分結果進行儲存,避免重複計算
class Solution_LC_343 {
    public int integerBreak(int n) {
        //記憶陣列
        int[] memo = new int[n];
        int ans = 0;
        //i表示第一個拆分值,該值必須小於n,因此不放在遞迴中
        for(int i=1; i<n; i++) {
            int tmp = integerBreak(n-i, i, memo);
            ans = (ans>tmp)? ans:tmp;
        }

        return ans;
    }
    //記憶化遞迴,memo[]儲存每個數rem的最優解 (0< rem < n)
    public int integerBreak(int rem, int curr, int memo[]) {
        //剩餘拆分值為0,1不需要繼續向下拆分
        if(rem==0 || rem==1) {
            return curr;
        }

        int result = 0;
        if(memo[rem]==0) {
            for(int i=1; i<=rem; i++) {
                int tmp = integerBreak(rem-i, i, memo);
                result = (result>tmp)? result:tmp;
            }
        }
        else {
            result = memo[rem];
        }

        return curr*result;
    }
}
  1. 動態規劃(優化)
class Solution_LC_343 {
    public int integerBreak(int n) {
        //dp[i]表示對i進行拆分後得到的最優解
        int[] dp = new int[n + 1];
        for (int i = 2; i <= n; i++) {
            int curMax = 0;
            for (int j = 1; j < i; j++) {
                //比較對剩餘拆分之(i-j)不進行拆分、進行拆分兩種結果
                curMax = Math.max(curMax, Math.max(j * (i - j), j * dp[i - j]));
            }
            dp[i] = curMax;
        }
        return dp[n];
    }
}