leetcode 343. Integer Break(dp或數學推導)


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.

For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).

Note: you may assume that n is not less than 2.

Hint:

  1. There is a simple O(n) solution to this problem.
  2. You may check the breaking results of n ranging from 7 to 10 to discover the regularities.

題意:給一個n(n>=2),求相加等於n且乘積最大的一組整數的積。

題解

這其實就是一道高中數學題,但是leetcode上的數據比較水,導致完全不用數學推導的O(n2)的dp也可以過。

解法一(純dp):

令dp[n]為n對應的最大積。

那么遞推方程就是:dp[n]=max(i*dp[n-i],i*(n-i))(其中i從1到n-1)。

邊界:dp[2]=1;

時間復雜度:O(n2)

class Solution {
public:
    int integerBreak(int n) {
        int dp[n];
        dp[1]=1;
        dp[2]=1;
for(int i=3;i<=n;i++){
            dp[i]=-1;
            for(int j=1;j<i;j++){
                dp[i]=max(j*dp[i-j],max(dp[i],j*(i-j)));
            }
        }
        return dp[n];
    }
};

解法二(當成數學題來做就好):

由均值不等式(n個數的算術平均數大於等於它們的幾何平均數):

\mathbf{A}_n =  \frac{x_1 + x_2 + \cdots + x_n}{n}    >=   \mathbf{G}_n = \sqrt[n]{x_1 \cdot x_2 \cdots x_n}

得:當把輸入的n拆分成幾個相等的數時它們的積最大。

那么問題來了,拆分成幾個呢?

為了方便使用導數,我們先假設我們可以把n拆分成實數。那么設每一個數為x,則一共有n/x個數。

設它們的積為f(x),則f(x)=x(n/x),那么怎么求f(x)最大值呢?求導數!

f′(x)=(n/x2)  *  x(n/x)  * (1-lnx)

當x=e時取極大值。

而我們題目里規定x為整數,那么我們只需要取的x越靠近e越好。那么2<e<3,而且e=2.71828...,所以取3是最好的,如果取不到3就取2。

冪運算復雜度為O(lgn),所以這個算法復雜度為O(lgn)。

class Solution {
public:
    int integerBreak(int n) {
        if(n == 2)
            return 1;
        else if(n == 3)
            return 2;
        else if(n%3 == 0)
            return pow(3, n/3);
        else if(n%3 == 1)
            return 2 * 2 * pow(3, (n - 4) / 3);
        else 
            return 2 * pow(3, n/3);
    }
};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM