• [LeetCode] 343. Integer Break


    Medium

    Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get.

    Example 1:

    Input: 2
    Output: 1
    Explanation: 2 = 1 + 1, 1 × 1 = 1.

    Example 2:

    Input: 10
    Output: 36
    Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36.

    Note: You may assume that n is not less than 2 and not larger than 58.

    题目大意:每个正整数都能拆分成至少两个大于零的数之和,给出一个正整数n,求出有这个正整数拆分出的数字的最大乘积。

    方法:

    因为不限制拆分的数字个数,所以一个正整数可以有很多种拆分方式,如果每一种情况都去计算乘积,然后比较得出最大值一定会浪费很多时间。我们考虑动态规划的方法。每个数字都可以拆分成两个数字,然后这两个数字再拆分成更小的两个数字,直至数字为2,因为数字2只有一种拆分情况,可将其设为初始边界条件。这样我们就不用考虑拆分成多个数字的情况,只要保留较小数字的结果来表示较大数字的结果就好了。然后我们对数字进行拆分来观察变化规律:

    2 1*1 1
    3 2*1 2
    4 2*2 4
    5 3*2 6
    6 3*3 9
    7 3*4 12
    8 6*2 18
    9 6*3 27
    10 6*4 36
    11 6*5 54
    12 6*6 81
    13 6*7 108
    14 12*2 162

    我多写个几个例子,因为直到这么多例子我才发现了一个规律,这里需要先注意一下,表中写的乘积的两个数字不是直接将两数相乘,这两个数字是可以继续拆分的,我们已知较小数字的结果,那么我们用他们的结果相乘就是我们的结果了。

    我们将2作为初始条件,5及其以后的数字都可以用3(和3的倍数)乘以一个数字表示,比如说5~7这部分就是3*m,m的范围是2~(3+1),8~13这部分是6*m,m范围是2~(6+1),以此类推。2和3是最基础的数字,他们可以组合出所有单双数。因为2和3的结果比本身要小,所以在用小数字结果计算大数字结果的时候要注意判断,选择最大的那个数参与计算。

    数字3和4从2得来,分别乘以1和2。由这些规律我们可以维护一个大小为n+1的向量dp,n的结果就是dp[n]。代码如下:

    class Solution {
    public:
        int integerBreak(int n) {
            vector<int> dp(n + 1, 0);
            dp[2] = 1;
            int level = 2, cur = 1;
            int p = 0;
            for (int i = 3; i <= n; ++i) {
                if ((level == 2 && cur<=level) || (level > 2 && cur <= level + 1)) {
                    dp[i] = max(dp[level],level) * max(dp[cur],cur);
                    cur++;
                }
                else {
                    level = 3 * pow(2, p++);
                    cur = 2;
                    i--;
                }
            }
            return dp[n];
        }
    };

    看到网上的博主分析,每个数字都拆分出3,然后直到剩下的数字是2或者3为止。也就是从5开始,每个数的结果就是数字中包含的3个个数个3相乘,然后乘以剩下的数中包含的2的个数个2相乘。

    代码如下:

    class Solution {
    public:
        int integerBreak(int n) {
            if(n==2 || n==3)return n-1;
            if(n==4)return n;
            n-=5;
            return (int)pow(3,n/3+1)*(n%3+2);
        }
    };
  • 相关阅读:
    2020软件工程作业04
    2020软件工程作业03
    2020软件工程作业02
    2020软件工程作业01
    2020软件工程作业02
    2020软件工程作业01
    WEB学习路线2019完整版(附视频教程+网盘下载地址)
    (2018干货系列七)最新大数据学习路线整合
    (2018干货系列六)最新云计算学习路线整合
    (2018干货系列五)最新UI设计学习路线整合
  • 原文地址:https://www.cnblogs.com/cff2121/p/12035089.html
Copyright © 2020-2023  润新知