LeetCode343. 整数拆分

思路: 画出递归树可以看出,存在重叠子问题,且具有最优子结构,因此可以使用 动态规划 解决。

(1)使用递归进行编码, 提交到力扣会超时

class Solution {
    public int integerBreak(int n) {
        return breakInteger(n);
    }
    // 将n进行分割(至少分割两部分),可以获得的最大乘积
    private int breakInteger(int n) {
        if (n == 1) return 1;
        int res = -1;
        for (int i = 1; i <= n - 1; i++) {
            // i + (n - i)
            // ① 不分割 (n-i),这样满足至少分割为两部分   ② 继续分割 (n-i)
            res = Math.max(res, Math.max( i * (n - i), i * breakInteger(n - i)) );
        }
        return res;
    }
}

(2)记忆化搜索(自顶向下),耗时 0ms ,100%

class Solution {
    public int integerBreak(int n) {
        int[] memo = new int[n + 1];
        Arrays.fill(memo, -1);
        return breakInteger(n, memo);
    }
    // 将n进行分割(至少分割两部分),可以获得的最大乘积
    private int breakInteger(int n, int[] memo) {
        if (n == 1) return 1;
        if (memo[n] != -1) {
            return memo[n]; // 将记录的结果直接返回
        }
        int res = -1;
        for (int i = 1; i <= n - 1; i++) {
            // i + (n - i)
            // ① 不分割 (n-i),这样满足至少分割为两部分   ② 继续分割 (n-i)
            res = Math.max(res, Math.max( i * (n - i), i * breakInteger(n - i, memo)) );
        }
        memo[n] = res; // 记录结果
        return res;
    }
}

(3)动态规划

class Solution {
    public int integerBreak(int n) {
        // 1. 状态的定义:dp[i]表示将数字i分割(至少分割成两部分)后得到的最大乘积
        int[] dp = new int[n + 1];
        Arrays.fill(dp, -1);
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {
            // 求解dp[i]
            for (int j = 1; j <= i-1; j++) {
                // j + (i - j)
                dp[i] = Math.max(dp[i], Math.max( j * (i - j), j * dp[i-j]) );
            }
        }
        return dp[n];
    }
}
原文地址:https://www.cnblogs.com/HuangYJ/p/14217061.html