標籤:tput inline 因子 isp def turn end object input
問題
將一個正整數分成至少兩個正整數的和,使得最大化這些整數的乘積,給出最大乘積。
Input: 10
Output: 36
Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
思路
什麼時候pq > p + q,只要p和q都大於1就滿足。在正整數裡,兩個為2時pq==p+q,所以只要一個至少為2,另一個至少為3即可,也就是p+q至少為5,那麼只要一個數大於等於5,就可以把這個數分解成p+q,使得pq > p + q,如果p或者q裡面還有大於等於5的數,就將p或q繼續分解,不斷往下分解,直到因子小於5。
因為要分解到小於5,所以最後的因子一定是2或者3(或者4),因為分成4和分成2是一樣的(兩個2和1個4的乘積相同),所以我們考慮3和2要怎麼分配。
考慮一個數有m個3和n個2相加,即\(x = 3m + 2n\),那麼積等於m個3和n個2相乘,定義一個函數,\(f = 3^m * 2^n = 3^m * 2^{\frac{x - 3m}{2}}\),可以得到$ln f $是一個關於m遞增的函數,如下公式所示。所以m越大越好,m表示3的個數,也就是說分解的時候盡量分多一些3,分到不能分再分2。
\[\begin{split}ln\ f &= m * ln3 + \frac{x - 3m}{2} * ln2 \ &= \frac{x}{2} ln \ 2 + (ln\ 3 - \frac{3}{2}ln\ 2)*m \end{split}\]
時間複雜度O(n),空間複雜度O(1)
代碼
class Solution(object): def integerBreak(self, n): """ :type n: int :rtype: int """ if(n == 2 or n == 3): return n-1 res = 1 while(n>=5): n -= 3 res *= 3 res *= n return res
出於以下考慮,還可以這麼寫。
如果n%3 == 0,可以分解成n/3個3,它們的積為\(3^{n/3}\)。
如果n%3 == 1,說明和的形式為n/3 * 3 + 1,把其中一個3和單獨的1改寫為2個2,它們的積為\(3^{n/3-1} * 2 * 2\)。
如果n%3 == 2,說明和的形式為n/3 * 3 + 2,它們的積為\(3^{n/3} * 2\)。
class Solution(object): def integerBreak(self, n): """ :type n: int :rtype: int """ if n>=4: if n%3 == 0: return 3**(n/3) if n%3 == 1: return 3**(n/3-1)*4 else: return 3**(n/3)*2 return n-1
343. Integer Break