思路: 画出递归树可以看出,存在重叠子问题,且具有最优子结构,因此可以使用 动态规划 解决。
(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]; } }