簡體   English   中英

關於python遞歸的困惑

[英]Confusion about python recursion

我正在編寫一個遞歸函數來解決一個問題,在該問題上,您實際上是在嘗試查找所有組合以達到給定數量的目標總和,而每個數字都小於某個限制。

我寫的代碼如下所示:

results = []

def findSchedulesHelper(workHours_left, dayHoursLimit, days_left, res):
    if workHours_left < 0:
        return
    elif workHours_left > 0 and days_left == 0:
        return
    elif workHours_left == 0 and days_left != 0:
        for i in range(days_left):
            res.append(0)
        results.append(res)
        return
    elif days_left == 0 and workHours_left == 0:
        results.append(res)
        return
    else:
        for i in range(dayHoursLimit + 1):
            res.append(i)
            findSchedulesHelper(workHours_left - i, dayHoursLimit, days_left - 1, res)
            res.pop()


def findSchedules(workHours, dayHours, pattern):
    # Write your code here
    num_question_mark = 0
    total_hours_so_far = 0
    for char in pattern:
        if char == "?":
            num_question_mark += 1
        else:
            total_hours_so_far += int(char)

    hours_left_to_fill = workHours - total_hours_so_far

    for i in range(dayHours + 1):
        findSchedulesHelper(hours_left_to_fill - i, dayHours, num_question_mark - 1, [i])
    print results

findSchedules(3,2,"??2??00")

但這給出了錯誤的答案。

如果我更改一行並使其:

results = []

def findSchedulesHelper(workHours_left, dayHoursLimit, days_left, res):
    if workHours_left < 0:
        return
    elif workHours_left > 0 and days_left == 0:
        return
    elif workHours_left == 0 and days_left != 0:
        for i in range(days_left):
            res.append(0)
        results.append(res)
        return
    elif days_left == 0 and workHours_left == 0:
        results.append(res)
        return
    else:
        for i in range(dayHoursLimit + 1):
            findSchedulesHelper(workHours_left - i, dayHoursLimit, days_left - 1, res + [i])


def findSchedules(workHours, dayHours, pattern):
    # Write your code here
    num_question_mark = 0
    total_hours_so_far = 0
    for char in pattern:
        if char == "?":
            num_question_mark += 1
        else:
            total_hours_so_far += int(char)

    hours_left_to_fill = workHours - total_hours_so_far

    for i in range(dayHours + 1):
        findSchedulesHelper(hours_left_to_fill - i, dayHours, num_question_mark - 1, [i])
    print results

findSchedules(3,2,"??2??00")

那么一切都是正確的。 我真的很困惑為什么會這樣。 我嘗試進行一些調試,發現append和pop未能按我預期的方式工作。 如果任何人都可以解釋我執行此功能的兩種方式之間的確切區別,那將是很好的。

第一個程序將一個項目添加到res的末尾,對findSchedulesHelper()進行遞歸調用,並在調用之后刪除添加的項目:

res.append(i)
findSchedulesHelper(workHours_left - i, dayHoursLimit, days_left - 1, res)
res.pop()

而第二個程序將傳遞一個新列表,該列表包含res所有內容以及額外的項目。 遞歸調用后無需清理:

findSchedulesHelper(workHours_left - i, dayHoursLimit, days_left - 1, res + [i])

兩者之間的差異是由於以下代碼:

for i in range(days_left):
    res.append(0)

也就是說,對findSchedulesHelper()的遞歸調用有可能更改res 如果是這樣,則返回時的res.pop()可能會刪除您認為不是的其他內容。 並有可能在年底要格外數據res上的下一個電話。 第二個程序不會遇到此問題,因為它傳遞了res副本,並且再也不會查看或重復使用該副本。

下一個潛在的問題是多次調用:

results.append(res)

在第一個程序中,您傳遞的是相同的res列表,因此results以指向res多個指針結尾,所有這些指針都是相同的精確列表,始終反映其當前狀態,而不是添加到results時的狀態。 在第二個程序中,您傳遞的是res的副本,因此results上的所有條目都是不同的 ,即res添加到results時的狀態。

暫無
暫無

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

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