算法题 一 之 整数拆分

整数拆分

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

例如:输入10,输出36。10 可以 拆分成3 3 4, 3 * 3 * 4 = 36。

分析案例
  • 10 拆成 3、3、4 时是最好的解。而这其中涉及了两步拆解。
  • 10 可以先拆成 6、4,由 6 再去拆解成 3、3,10 也可以先拆成 3 、7,由7再去拆成3、4
算法
  • 由上述分析得知,任何一个数可以先拆成两个,然后由其中一个再去进行拆分
为什么是其中一个,不需要两个数字一起拆分?
  • 再拿10来分析,10 可以拆成5 和 5,那么应该5和5一起拆分啊。因为 5 * 2 * 3 < 2 * 3 * 2 * 3啊,这样不就是漏掉了一些可能了吗?
  • 目前看来好像是应该两个都拆分,其实两个都拆分也没错,只是多余而已。因为2 * 3 * 2 *3 可以看成把10 拆成 2 * 8,而 2 * 8这种情况,我们一定也会计算到的。
定义状态和状态转移方程式
  • 定义 dp[n] :当前的拆分完后的最好的值。
  • 方程转移:dp[n] = Max(Max((j∈ 1 到 N) * N - j) ,(j∈ 1 到 N) * dp[N - j]),dp[n])
  • 注意:状态转移方程需要对比一下 dp[n] 因为dp[n] 可分割为多种组合
附上代码:
public int integerBreak(int n) {

   // 动态规划 dp[i]:当处于i时,拆分了至少两个以上的最大乘积
   // 第一步:定义 i ,i代表 2 .... n 的循环,所以 i 可分割为 两个数,定分割点为 j。
   //         所以,dp[i] 可以是 j * (i - j),而这里有一个很关键的地方是,j 和 (i - j)是可以继续往下分割的。
   //         而 j 和 i - j 只需要考虑i - j即可,因为把j继续往下拆分的情况已经考虑过了,请看上述的分析
   //         综上所述 状态转移方程为:dp[i] = max(j * (i - j),j * dp[i-j]);
   // 第二步:dp[n] 即是答案。

   int[] dp = new int[n + 1];
   for (int i = 2; i <= n; i++){//记住 需要包括n 因为n代表是一个数字 而不是下标
       //遍历分割点
       for(int j = 1; j < i;j++){
           dp[i] = Math.max(Math.max(j * (i - j), j * dp[i - j]),dp[i]);
       }
   }
   return dp[n];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值