zoukankan      html  css  js  c++  java
  • 343. Integer Break

    问题:

    将给定正整数n,拆成多个数。(使得这些数之和=n)

    这些数之积最大是多少。

    Example 1:
    Input: n = 2
    Output: 1
    Explanation: 2 = 1 + 1, 1 × 1 = 1.
    
    Example 2:
    Input: n = 10
    Output: 36
    Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36.
     
    Constraints:
    2 <= n <= 58
    

      

    解法:DP,math

    解法一:DP

    • 状态:dp[n]:n被拆分后所得最大乘积
      • 要被拆分的数 n
    • 选择:
      • 拆出去x=1~n-1中任意数,和剩下的数n-x,被拆分后的最大乘积,相乘所得结果中的最大值。
      • MAX {(x:1~n-1)
        • dp[n-x] * x
      • }
    • base:
      • dp[1]=1
      • dp[2]=1

    ⚠️ 注意:当得到 当前数 n 的拆分最大结果 dp[n] 后,

    为求解后面的数 >n ,n 自己也可作为乘数,不拆分,因此dp[n] = max(n,dp[n]),用 自己 和 刚才求得结果dp[n] 之间,再求最大值。

    代码参考:

     1 class Solution {
     2 public:
     3     //dp[n]:maximum product of divide n.
     4     //opt: MAX:(x=1~n-1)
     5     // = dp[n-x] * x
     6     //base:
     7     //dp[1]=1
     8     //dp[2]=1
     9     int integerBreak(int n) {
    10         vector<int> dp(n+1,0);
    11         int res = 0;
    12         dp[1]=1;
    13         dp[2]=1;
    14         for(int i=3; i<=n; i++) {
    15             dp[i-1] = max(i-1, dp[i-1]);
    16             //i-1: as itself(not to divide) -> for other element calculate.
    17             for(int x=2; x<=i-1; x++) {
    18                 dp[i] = max(dp[i], dp[i-x]*x);
    19             }
    20         }
    21         return dp[n];
    22     }
    23 };

    解法二:math

    思路:要使 拆分n 的乘积取得最大。

    我们先考虑,将 n 拆分为两个数 f=x(N-x) (以后在递归拆分这两个数即可)

    怎么样才能使得 f 最大,可得:

    x=N/2,我们能得到最大。

    由于根据题意,我们需要拆分成两个正整数。那么分奇偶性讨论:

    • N为偶数:(N/2)*(N/2)
    • N为奇数:((N+1)/2) * ((N-1)/2)

    要使其结果>=N

    那么可得:

    • N为偶数:N>=4
    • N为奇数:N>=5

    也就是说,只要N>=4,都可被拆分成两个更小的数,使得乘积更大。

    那么,能作为乘积的数只有:1,2,3

    • 1*任何数都不能变大,因此排除 1
    • 只能在2 和 3 中选择拆分因数。
      • 我们优先选择3,理由是:
        • 例如 N=6,
        • 3*3>2*2*2
      • 我们选择先拆分为3,能得到选择2更大的结果。

    总结:

    我们对N>=4的数可进行优先拆分出3,循环拆分,

    直到拆分不出来3,就其次选择2。

    ⚠️ 注意,要排除最终拆出个 1 的情况,这样只会削减结果。

    例如,4->

    先拆分 3 的话,剩下一个 1。因此我们不能选择这种拆法

    其次选择拆分 2,再留下个 2。选择这种拆分法。

    代码参考:

     1 class Solution {
     2 public:
     3     int integerBreak(int n) {
     4         if(n==2) return 1;
     5         if(n==3) return 2;
     6         int product = 1;
     7         while(n>4) {
     8             product *= 3;
     9             n-=3;
    10         }
    11         product *= n;
    12         return product;
    13     }
    14 };
  • 相关阅读:
    Python笔记初识
    visio开发者图形分类个人爱好
    亿图图示与visio结合使用
    xmind visio mindmanager edraw比较
    Pycharm安装步骤
    win32com问题
    Win32.com安装
    Pycharm安装步骤
    Phython笔记初识
    跨域问题解决方案
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/14657537.html
Copyright © 2011-2022 走看看