給定乙個正整數 n,將其拆分為至少兩個正整數的和,並使這些整數的乘積最大化。 返回你可以獲得的最大乘積。
示例 1:
輸入: 2
輸出: 1
解釋: 2 = 1 + 1, 1 × 1 = 1。
示例 2:
輸入: 10
輸出: 36
解釋: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
說明: 你可以假設 n 不小於 2 且不大於 58。
第一種方法:
動態規劃
對於正整數n(n>=2),最少有兩個正整數組成,令k是拆分的第乙個正整數,n-k就是剩餘的數,n-k可以不進行拆分,也可以進行拆分。因為每個正整數對應的最大乘積取決於比他小的數的乘積,因此可以用動態規劃來進行。
首先我們建立乙個陣列a[n],對於每個陣列的元素都存入對應下標的最大乘積值,對於0和1,我們就不進行存入。因此a[0]和a[1]就是0.
當i≥2的時候,假設對i進行拆分的第乙個數就是j(1≤j1.將i拆分成j和i-j的和,且i-j不拆分成更多的正整數 ,此時的乘積是j*(i-j)。
2.將i拆分成j和i-j的和,且i-j拆分成更多的正整數,此時的乘積就是ja[i-j]。
因此,當j固定的時候,
a[j]=max(j(i-j),j*a[i-j]).j的範圍是1~i-1.
由此遍歷即可。
int integerbreak
(int n)
dp[i]
= curmax;
}return dp[n]
;}
複雜度分析
時間複雜度:由於進行了兩層迴圈,所以時間複雜度應該是o(n^2).
空間複雜度:只需要陣列的開闢,所以空間複雜度是o(n).
另一種方法就是數學的計算:
利用函式極限值來:
將乙個給定的正整數拆分成某個特定的正整數,則這些正整數的乘積最大。
定義函式 f(x)表示將給定的正整數 n 拆分成盡可能多的正數 x 的情況下的最大乘積,則可以將n分成n/x項
因此f(x)=x^(n/x) =e^(ninx/x)。
令g(t)= e^t ,h(x)=inx/x,則有f(x)=g(n*f(x)),由於g(x)是單調遞增的,所以f(x)也是單調遞增的,(n>0).
計算h(x)的駐點,h』(x)=(1-inx)/x^2=0,得到駐點x=e.
在00,當x>e的時候h』(x)<0,因此x=e的時候是極大值。因此x=e的時候f(x)有最大值,f(x)max=f(e)=e^(n/e).
由於 e 不是整數,因此使用與 e 最接近的整數作為x 的值,x 可以是 2 或 3,此時需要比較 f(2) 與 f(3) 的大小,可以通過計算f(3)/f(2)的值
進行比較。
f(3)/f(2)的最終結果是e^(n/6*(in9-in8)),所以f(3)>f(2).
因此我們應該將給定的正整數拆分成更多的3.
根據n/3得到的餘數可以分為以下情況:
1.餘數為0,則n=3m(m≥2),則將n拆分成m個3.
2.餘數為1,則n=3m+1(m≥1),將n分成m-1個3和2個2.
3.當餘數為2的時候,則n=3m+2(m≥1),將n分成m個3和1個2.
上面適用的情況就是n≥4,當n≤3的時候就不適用了。
當n≤3,則結果返回乘積最大是(n-1)。
實現函式**如下:
int integerbreak
(int n)
int quotient = n /3;
int remainder = n %3;
if(remainder ==0)
else
if(remainder ==1)
else
}
(力扣每日一題)整數拆分
給定乙個正整數 n,將其拆分為至少兩個正整數的和,並使這些整數的乘積最大化。返回你可以獲得的最大乘積。動態規劃 1 對於的正整數 n,當 n 2 時,可以拆分成至少兩個正整數的和。2 令 kk是拆分出的第乙個正整數,則剩下的部分是 n k,n k 可以不繼續拆分,或者繼續拆分成至少兩個正整數的和。3...
每日一題 力扣 計畫
98 驗證二叉搜尋樹 問題給定乙個二叉樹,判斷其是否是乙個有效的二叉搜尋樹。假設乙個二叉搜尋樹具有如下特徵 1.節點的左子樹只包含小於當前節點的數。2.節點的右子樹只包含大於當前節點的數。3.所有左子樹和右子樹自身必須也是二叉搜尋樹。示例 1 輸入 2 1 3 輸出 true示例2 輸入 5 1 4...
力扣每日一題 6 14
1300 轉變陣列後最接近目標值的陣列和 給你乙個整數陣列 arr 和乙個目標值 target 請你返回乙個整數 value 使得將陣列中所有大於 value 的值變成 value 後,陣列的和最接近 target 最接近表示兩者之差的絕對值最小 如果有多種使得和最接近 target 的方案,請你返...