簡體   English   中英

python 中的遞歸 function 問題

[英]Issue with recursive function in python

我在遞歸定義此 function 時遇到問題。 我的目標是讓 function 從給定的n返回最大收入。 n (以米為單位)這里是布料的數量。 h列表是出售n米長的地毯時的利潤。 例如, h[2]=5是制作 2 米長的地毯時的利潤,為簡單起見是 5 美元,而h[0]=0因為沒有布可用,也沒有生產產品。 所以h榜只是不同長度的地毯的市場價值。 如果我有n米布,我希望 function 能夠返回最大利潤。 價格僅針對不超過 4 m 的地毯定義,因此h列表就是這樣。 例如, n=2的遞歸計算制造 2 m 大的地毯的價值,並將利潤與制造兩個 1 m 的地毯進行比較,依此類推。

遞歸大致表述為:

  • income(0) = 0
  • income(n) = max(h[i]+income(ni))對於1<=i<=n

截至目前,通過下面的代碼,我超出了遞歸限制。 我不覺得奇怪,因為我沒有限制循環的條件,但問題是我不知道如何繼續並定義某種約束。 我意識到這里的描述可能非常混亂,但請詢問,我會嘗試更廣泛地解釋。

def income(n):
    h = [0,2,5,6,9]
    for i in range(n):
        return max(h[i]+income(n-i))

編輯:這是我想出的解決方案。

def income(n):
    """Returns maximum profit by a given n."""
    h = [2,5,6,9,0]
    m = []
    if n == 0:
        return 0
    else:
        for i in range(n):
            m.append(h[i]+income(n-i-1))
    return max(m)

帶緩存:

def memoize(f):

    memo = {}
    def helper(x):
        if x not in memo:            
            memo[x] = f(x)
        return memo[x]
    return helper

income = memoize(income)

您要解決的問題是無界背包問題的一個版本。 與其試圖最大化你可以裝進一個包的價值,你正在嘗試最大化你可以用你的布制作的地毯的價值。 您不關心物品的重量,而是關心地毯上使用了多少布料。 但結果是一樣的。 無論如何,對於任意輸入,這是一個很難有效解決的問題,但是對於小的n值,您可以很容易地強制它。

您正確地確定了您的遞歸永遠持續(或者更確切地說直到遞歸限制),因為您沒有編寫基本案例。 它實際上比這更糟糕,因為第一次遞歸是i等於0 ,它再次調用 function 與您已經嘗試解決的完全相同的n (因為當i==0nin )。

i為零時,您真的不想遞歸,因為您根本不會減少問題的 scope。 最簡單的方法可能只是修改您的range以從i開始1 ,然后從那里增加。 您還需要一些邏輯來防止循環超過索引 4,因為列表中沒有更長的值。

def income(n):
    if n == 0:         # base case
        return 0
    h = [0,2,5,6,9]
    return max(h[i]+income(n-i) for i in range(1, min(n+1, len(h))))  # recursive case

除了為n==0添加基本情況並修復range之外,我還將循環替換為執行遞歸的生成器表達式。 這是必要的,因為max需要幾個 arguments (它相互比較),或單個可迭代參數(比較誰的值)。 您只傳遞了一個值,這是行不通的。

上面的版本適用於較小的n值,最大約為 15。但高於此值開始需要越來越長的時間,因為遞歸變得非常深入和廣泛,最終你會一遍又一遍地計算很多值。 這就是我說背包問題很難的意思!

一個可以大大加快速度的技巧是在您第一次計算出每個計算的結果時緩存它,並在以后再次需要時使用緩存的值。

_cache = {0: 0}   # the cache is pre-seeded to handle our base case of n=0
def income(n):
    if n not in _cache:
        h = [0,2,5,6,9]
        _cache[n] = max(h[i]+income(n-i) for i in range(1, min(n+1, len(h))))
    return _cache[n]

我還要注意,對於您的特定h列表,看起來總是最好制作盡可能多的 2 米地毯,如果您從n 因此,如果您願意對示例中非常具體的問題的最佳解決方案進行硬編碼,則可以跳過遞歸並執行以下操作:

def income(n):
   return n//2 * 5 + n%2 * 2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM