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];
    }
}