2017-04-12 51 views
-1

我試圖編寫一個遞歸函數來生成所有數字列表< N誰的總和等於N中的Python 這是我寫的代碼:遞歸函數python,創建生成具有相同總和的所有數字的函數N

def fn(v,n): 
    N=5 
    global vvi 
    v.append(n) ; 
    if(len(v)>N): 
     return 
    if(sum(v)>=5): 
     if(sum(v)==5): vvi.append(v) 

    else: 
     for i in range(n,N+1): 
      fn(v,i) 

這是輸出我得到

vvi 
Out[170]: [[1, 1, 1, 1, 1, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5]] 

我想同樣的事情,與C++和它工作得很好

+0

python和C++都是具有不同語法的不同語言。 – Surajano

+0

我沒有得到,你能提供更多關於輸入到你的代碼和相應輸出的細節嗎? –

+0

包括你如何第一次調用遞歸函數 – Adirio

回答

1

你可能要重新考慮遞歸的解決方案,並考慮動態規劃方法:

def fn(N): 
    ways = {0:[[]]} 
    for n in range(1, N+1): 
     for i, x in enumerate(range(n, N+1)): 
      for v in ways[i]: 
       ways.setdefault(x, []).append(v+[n]) 
    return ways[N] 

>>> fn(5) 
[[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 2, 2], [1, 1, 3], [2, 3], [1, 4], [5]] 
>>> fn(3) 
[[1, 1, 1], [1, 2], [3]] 

輸入參數使用global變量和副作用,一般認爲不好的做法,你應該避免的。

+0

這不是一個遞歸函數,但是... – skyking

+0

我相信我在我的文章的第一句話中提到這一點。 – AChampion

+0

它實際上不會返回重複的解決方案,如果只有元素存在而不是它們的順序,所以+1 – Adirio

2

你的東東是什麼要做的只是把它作爲一個遞歸描述來實現它。您想要將所有單身[j]預先加入到每個列表中,總和爲N-j,除非N-j=0其中您還將包含單身人士本身。翻譯成巨蟒,這將是

def glist(listsum, minelm=1): 
    for j in range(minelm, listsum+1): 
     if listsum-j > 0: 
      for l in glist(listsum-j, minelm=j): 
       yield [j]+l 
     else: 
      yield [j] 

for l in glist(5): 
    print(l) 

該解決方案包含了一種機制,將被要求列出排除置換的方案是非下降,這是通過minelm說法,在列表的其餘部分限制值來實現。如果您不想包含排列列表,則可以通過將遞歸調用替換爲glist(listsum-j)來禁用minelm機制。

至於你的代碼,我並不真正按照你想要做的。我很抱歉,但是你的代碼不是很清楚(只有在python中,這不是一件壞事,它實際上在C中更是如此)。

首先,通過全局變量返回函數的結果是一個壞主意,返回的結果是return的作用,但是在python中,如果你想返回多個元素,你也可以使用yield走。對於遞歸函數,通過全局變量返回(甚至使用它)更加可怕,因爲您正在運行函數的多個嵌套調用,但只有一個全局變量。

還調用函數fn將參數vn作爲參數。那實際上告訴了你關於功能和它的論點的是什麼?至多它是一個函數,可能其中一個參數應該是一個數字。如果有人(其他人)要閱讀和理解代碼,那麼這不是非常有用。

如果你想更詳細的回答你的代碼有什麼問題,你應該包括一個minimal, complete, verifiable example包括預期的輸出(也許觀察到的輸出)。

+0

他正在使用一個全局變量來存儲結果,這是一個可怕的做法 – Adirio

+0

@Adirio我沒有意識到這一點,但我同意這很可怕 - 所以我已經更新了答案,指出了我的解決方案中可能會讀錯的內容。至少更重要的一點。 – skyking

+0

你可能想重新考慮你的參數名'sum',隱藏python內建函數通常不是一個好主意。 – AChampion