簡體   English   中英

為什么后向遞歸比python中的前向遞歸執行得更快

[英]Why does backward recursion execute faster than forward recursion in python

我在Python中創建了一個算法,用於計算使用不同硬幣面額獲得金額的方式的數量:

@measure
def countChange(n, coin_list):
    maxIndex = len(coin_list)
    def count(n, current_index):        
        if n>0 and maxIndex>current_index:
            c = 0
            current = coin_list[current_index]
            max_coeff = int(n/current)      
            for coeff in range(max_coeff+1):
                c+=count(n-coeff*current, current_index+1)
        elif n==0: return 1
        else: return 0
        return c
    return count(n, 0)

我的算法使用索引來獲得硬幣面額,正如您所看到的,我的索引在我進入的每個堆棧幀中都在增加。我意識到算法也可以用這種方式編寫:

@measure
def countChange2(n, coin_list):
    maxIndex = len(coin_list)
    def count(n, current_index):        
        if n>0 and 0<=current_index:
            c = 0
            current = coin_list[current_index]
            max_coeff = int(n/current)      
            for coeff in range(max_coeff+1):
                c+=count(n-coeff*current, current_index-1)
        elif n==0: return 1
        else: return 0
        return c
    return count(n, maxIndex-1)

這一次,索引正在減少我進入的每個堆棧幀。我比較了函數的執行時間,我得到了一個非常值得注意的區別:

print(countChange(30, range(1, 31)))
print(countChange2(30, range(1, 31)))

>> Call to countChange took 0.9956174254208345 secods.
>> Call to countChange2 took 0.037631815734429974 secods.

如果我甚至沒有緩存結果,為什么算法的執行時間會有很大差異呢? 為什么索引的增加順序會影響執行時間?

根據我的理解,這與動態編程沒有任何關系。 只是扭轉指數不應​​該使某些東西“動態”。

發生的事情是算法是輸入敏感的 嘗試以相反的順序輸入輸入。 例如,

print(countChange(30, list(reversed(range(1, 31)))))
print(countChange2(30, list(reversed(range(1, 31)))))

正如一些排序算法對已經排序的數據非常快,而對於反向數據非常慢,你在這里得到了這種算法。

在輸入增加的情況下, countChange需要更多的迭代才能得出最終的答案,因此看起來要慢得多。 但是,當輸入減小時,性能特性會反轉。

數字組合並不大

原因是前進你必須探索每一種可能性,但是當你倒退時你可以消除大塊無效的解決方案而無需實際計算它們

今后你打電話數500k次

向后退你的代碼只能撥打30k電話來計算......

您可以通過記憶調用來更快地完成這兩項工作(或者將算法更改為不重復調用)

暫無
暫無

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

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