給你一根長度為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。
遇到問題,先分析問題,由分析的結果確定所運用的演算法。
一般而言,我們都會在紙上動筆畫畫,羅列一些基本的情況。
題中說n>1並且m>1,那麼
參考n= x的情況,如果把長度n繩子的最大乘積記為f(n),則有:f(n)=max(f(i)*f(n-i)),0當你分析到這個的時候,思路就得到了一層的突破:從下往上推,先算小的問題,再算大的問題,大的問題通過尋找小問題的最優組合得到。這個不就是動態規劃
嗎?
動態規劃演算法的定義是通過拆分
問題,定義問題狀態和狀態之間的關係
,使得問題能夠以遞推(或者說分治)的方式去解決。
既然寫到了動態規劃,那我就將我所知道的都告訴你:
關於動態規劃演算法定義的理解
至於演算法思想的理解,我們解答中**
這個涉及到乙個數學模型,原本的定義非常巨集大和複雜,這裡不多贅述,我們這裡只是涉及到一丁點的應用,你有個印象即可。
我們之前也討論了,剛才的遞推式f(n)=max(f(i)*f(n-i)),0對於任意乙個大於或者等於5的數字,都可分解為加數 2 和 3的和。(這個小學數學就能證明,不證明了哈)
遞推式涉及到乘積,很容易注意且能證明3(length-3)>2(length-2),因此要想乘積最大,盡可能分出更多的加數3
除了上述所說的,我們還有乙個特殊的數字就是4,當length=4的時候,13<22=4,所以length=4的時候不用再分。
區域性最優能保證整體最優,貪心演算法寫起來要比動態規劃簡單多了。
/**
* @param length 輸入的繩子的長度
* @return 乘積的最大值
* 動態規劃的演算法思想:
* 動態規劃演算法的基本思想與分治法類似,也是將待求解的問題分解為若干個子問題(階段),按順序求解子階段,前一子問題的解,為後一子問題的求解提供了有用的資訊。
* 在求解任一子問題時,列出各種可能的區域性解,通過決策保留那些有可能達到最優的區域性解,丟棄其他區域性解。依次解決各子問題,最後乙個子問題就是初始問題的解。
*/public int maxproductaftercutting(int length)
// 把最優解儲存下來(為了後面的使用的最優解,為區域性最優解)
product[n] = max;
}return product[length];
}
public int maxproductaftercutting(int length)
int timesoftwo = (length - timesofthree * 3) / 2;
return (int) (math.pow(3, timesofthree) * math.pow(2, timesoftwo));
}
劍指Offer對答如流系列 醜數
我們把只包含質因子2 3和5的數稱作醜數 ugly number 求按從小到大的順序的第n個醜數。例如6 8都是醜數,但14不是,因為它包含質因子7。習慣上我們把1當做是第乙個醜數。判斷乙個數是不是醜數,最容易想到的方法就是讓這個數不斷除以2,3,5。對於第n個醜數,只要從1開始,依次判斷每個數是不...
劍指Offer對答如流系列 包含min函式的棧
定義棧的資料結構,請在該型別中實現乙個能夠得到棧的最小元素的min函式。在該棧中,呼叫min push及pop的時間複雜度都是o 1 push 和 pop均容易實現。主要就是min函式的定義,如果要通過操作push和pop操作獲取最小元素時間複雜度為o 1 基本上是不可能的。如果我們另外定義乙個成員...
劍指Offer對答如流系列 樹的子結構
輸入兩棵二叉樹a和b,判斷b是不是a的子結構。二叉樹的定義如下 public class treenode 比如下面的 b是a的子結構 看了看 劍指offer 高質量 章節的面試題,發現難度都不高,但是沒有分析好邊界條件亦或是想當然就是容易出錯,細心從來不是說說而已。請重視自己 的規範性 完整性和魯...