題目
給定一個正整數 n
,將其拆分爲至少兩個正整數的和,並使這些整數的乘積最大化。 返回你可以獲得的最大乘積。
示例 1:
輸入: 2
輸出: 1
解釋: 2 = 1 + 1, 1 × 1 = 1。
示例 2:
輸入: 10
輸出: 36
解釋: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
函數原型
C
的函數原型:
int integerBreak(int n){}
邊界判斷
說明: 你可以假設 n 不小於 2 且不大於 58。
那就不需要邊界判斷。
算法設計:遞歸
從後往前看,如分割 4
。
分割 4
就有 3
個備選答案,分割 4
的最大乘積是:
- 分割
3
的最大乘積 *1
(拆分下來的,計算乘積最大值) = 一個備選答案 - 分割
2
的最大乘積 *2
= 一個備選答案 - 分割
1
的最大乘積 *3
= 一個備選答案
分割 4
的最大乘積 = 選出一個最大的備選答案。
分割 1
的最大乘積 就是 1
,那分割 2
和 分割 3
的最大乘積呢?
不斷拆分即可。
一般化:
inline int max(int x, int y, int z){
return (x>y?x:y)>z?(x>y?x:y):z;
}
int integerBreak(int n){
if( n == 1 )
return 1;
int max_ans = 0;
for(int i=1; i<=n-1; i++)
max_ans = max(max_ans, i*(n-i), i*integerBreak(n-i));
return max_ans;
}
遞歸的複雜度:
- 時間複雜度:
- 空間複雜度:
算法設計:遞歸+記憶化搜索
遞歸有重複計算子問題,爲啥,我們不創建一個容器來存儲這些值,避免重複計算呢?
inline int max(int x, int y, int z){
return (x>y?x:y)>z?(x>y?x:y):z;
}
int memo[64];
int integerBreak(int n){
if( n == 1 )
return 1;
if( memo[n] ) // 已經計算過
return memo[n];
int max_ans = 0;
for(int i=1; i<=n-1; i++)
max_ans = max(max_ans, i*(n-i), i*integerBreak(n-i));
memo[n] = max_ans;
return max_ans;
}
遞歸+記憶化搜索複雜度:
- 時間複雜度:
- 空間複雜度:
算法設計:動態規劃
這個問題中,我們從後往前分析,發現有重疊子問題,我們就可以使用記憶化搜索。
而解決子問題,就可以解決原問題,動態規劃就是要解決這類問題的。
關於動態規劃,請猛擊:《動態規劃》。
inline int max(int x, int y, int z){
return (x>y?x:y)>z?(x>y?x:y):z;
}
int memo[64];
int integerBreak(int n){
memo[1] = 1;
for( int i=2; i<=n; i++ )
for( int j=1; j<=i-1; j++ )
memo[i] = max(memo[i], j*(i-j), j*memo[i-j]);
return memo[n];
}
動態規劃的複雜度:
- 時間複雜度:
- 空間複雜度: