劍指offer算法題【13】:剪繩子(動態規劃以及貪心算法)

 題目

 思路

動態規劃

如果要求一個問題的最優解,而且該問題能分成若干個子問題,整體問題的最優解依賴於子問題的最優解,可以考慮用動態規劃解決。

動態規劃一般是自頂向下思考,自底向上實現的,爲什麼字底向上呢?因爲字底向上所消耗的內存空間少很多,爲了避免計算子問題時重複,可以將子問題的結果記錄下來。

先自上而下分析,在長度爲n的繩子所求爲f(n),剪下一刀後剩下的兩段長度是i和n-i,在這個上面還可能繼續減(子問題),所以:

                                     

代碼

class Solution:

    def solution1_DP(self,length):
        if length < 2:  # 因爲要求長度n>1,所以這裏返回0表示輸入非法
            return 0
        if length == 2:
            return 1    # 長度爲2時,因爲要求剪下段數m>1,所以最大是1x1=1
        if length ==3:
            return 2    # 長度爲3時,因爲要求剪下段數m>1,所以最大是1x2=1

        """運行至此, 說明繩子的長度是 > 3的, 這之後當切割成0 / 1 / 2 / 3
        這種子問題最大解就是其自身長度而不再需要考慮剪一刀的問題, 
        因爲它們剪一刀沒有不剪來的收益高,比如說,當繩子長度是4時,就有1*3,2*2兩種情況,而沒有必要說f(4) = f(1) * f(3) = 0*2 = 0。
        而在當下這麼長的繩子上剪過纔可能生成0 / 1 / 2 / 3
        這種長度的繩子, 它們不需要再減
        所以下面的表中可以看到它們作爲子問題的值和上面實際返回的是不一樣的"""

        max_len = 0
        max_len_array = [0] * (length+1)
        max_len_array[0] = 0
        max_len_array[1] = 1
        max_len_array[2] = 2
        max_len_array[3] = 3

        for i in range(4,length+1):
            max_len = 0  # 每次將最大乘積清空,因爲要計算f(j)乘以f(i-j)的最大值,j超過i的一半時是重複計算,所以只需要考慮j不超過i的一半的情況
            for j in range(1,i//2+1):
                tmp = max_len_array[j] * max_len_array[i-j] # 計算f(j)*f(i-j)
                if max_len  < tmp:
                    max_len = tmp # 更新最大值
            max_len_array[i] = max_len
        return max_len



if __name__ == '__main__':
    s = Solution()
    print(s.solution1_DP(8))

運行結果:

發佈了234 篇原創文章 · 獲贊 71 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章