給你一根長度為 n 的繩子,請把繩子剪成整數長度的 m 段(m、n都是整數,n>1並且m>1),每段繩子的長度記為 k[0],k[1]...k[m-1] 。
請問 k[0]*k[1]*...*k[m-1] 可能的最大乘積是多少?
例如,當繩子的長度是8時,我們把它剪成長度分別為2、3、3的三段,此時得到的最大乘積是18。
示例 1:
輸入: 2示例 2:輸出: 1
解釋: 2 = 1 + 1, 1 × 1 = 1
輸入: 10在做這題之前我們先來看這樣乙個問題,乙個整數先把他分成兩部分,x+y=n(假設x>=y並且x-y<=1,也就是說x和y非常接近)那麼乘積是x*y。然後我們再把這兩部分的差放大(x+1)+(y-1)=n(假設x>=y);他們的乘積是(x+1)*(y-1)=x*y-(x-y)-1,很明顯是小於x*y的,所以我們得出結論,如果把整數n分為兩部分,那麼這兩部分的值相差越小乘積越大。輸出: 36
解釋: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
同理還可以證明如果分成3部分,4部分……也是相差越小乘積會越大。
根據上面的證明,如果我們把長度為n的繩子分為x段,則每段只有在長度相等的時候乘積最大,那麼每段的長度是n/x。所以他們的乘積是(n/x)^x。我們來對這個函式求導
通過對函式求導我們發現,當x=n/e的時候,也就是每段繩子的長度是n/x=n/(n/e)=e的時候乘積最大。我們知道e=2.718281828459。而題中我們的繩子剪的長度都是整數,所以不可能取e,我們只能取接近e的值,也就是3的時候乘積最大。
但也有例外,當n<=4的時候會有特殊情況,因為2*2>1*3。明白了這點**就容易多了,如果n大於4,我們不停的把繩子減去3,來看下**
public int cuttingrope(int n) return n * res;}
或者如果不想使用迴圈,我們還可以使用公式
public int cuttingrope(int n) else if (n % 3 == 1) else }
定義乙個陣列dp,其中dp[i]表示的是長度為i的繩子能得到的最大乘積。我們先把長度為i的繩子拆成兩部分,一部分是j,另一部分是i-j,那麼會有下面4種情況
1,j和i-j都不能再拆了
2,j能拆,i-j不能拆
3,j不能拆,i-j能拆
4,j和i-j都能拆
我們取上面4種情況的最大值即可。我們把它整理一下,得到遞推公式如下
dp[i] = max(dp[i], (max(j, dp[j])) * (max(i - j, dp[i - j])));
比如我們想計算長度為9的繩子,畫個圖來看一下
計算長度為9的繩子之前,我們必須要先計算長度為8的繩子。對於長度為9的繩子我們可以先分為兩部分,每一部分都取最大值,然後相乘。
最後再來看下**
public int cuttingrope(int n) { int dp = new int[n + 1]; dp[1] = 1; for (int i = 2; i <= n; i++) { for (int j = 1; j
這題應該說更像是一道數學題,使用數學的方式很容易解決,動態規劃的遞推公式可能不太容易想到。 劍指Offer 剪繩子 和剪繩子
劍指offer 剪繩子 題目描述 給你一根長度為 n 的繩子,請把繩子剪成整數長度的 m 段 m n都是整數,n 1並且m 1 每段繩子的長度記為 k 0 k 1 k m 請問 k 0 k 1 k m 可能的最大乘積是多少?例如,當繩子的長度是8時,我們把它剪成長度分別為2 3 3的三段,此時得到的...
劍指offer 剪繩子
題目 給你一根長度為n繩子,請把繩子剪成m段 m n都是整數,n 1並且m 1 每段的繩子的長度記為k 0 k 1 k m k 0 k 1 k m 可能的最大乘積是多少?例如當繩子的長度是8時,我們把它剪成長度分別為2 3 3的三段,此 時得到最大的乘積18。思路 動態規劃 任何動態規劃都是由遞迴演...
《劍指Offer》剪繩子
給你一根長度為n的繩子,請把繩子剪成m段 m n都是整數,n 1並且m 1 每段繩子的長度記為k 0 k 1 k m 請問k 0 xk 1 x.xk m 可能的最大乘積是多少?例如,當繩子的長度是8時,我們把它剪成長度分別為2 3 3的三段,此時得到的最大乘積是18 乘法計算,除了一以外,越多的數相...