簡體   English   中英

用遞歸解決DFS問題它是如何工作的?

[英]DFS problem solving with recursion how does it work?

問題來了

有 n 個非負整數。 我們想適當地添加或減去這些數字以制作我們的目標數字。 例如,要使 [1, 1, 1, 1, 1] 中的數字為 3,可以使用以下五種方法:

-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3

編寫求解函數,以數組編號、目標編號和目標作為參數時,通過適當加減數字來返回生成目標編號的方法數。

限制

  • 給出的數字個數為 2 或更多且 20 或更少。
  • 每個數字都是 1 到 50 之間的自然數。
  • 目標數是 1 到 1000 之間的自然數。

輸入/輸出示例

numbers: [1,1,1,1,1]
target: 3
return: 5

方法

                                    1

                                  /   \

                               -1       1

                             /   \     /   \

                           -1     1  -1     1
                           
                           -1     1   1     3

以 DFS 方式找到了這種方法,檢查所有情況,如果數字的組合等於目標數,則加法或減法然后計數。

代碼如下:

def solution(numbers, target):
    total = 0
    num_len = len(numbers)

    def dfs(index=0):
        if index < num_len:
            numbers[index] *= 1
            print('positive / index', index, numbers)
            dfs(index + 1)

            numbers[index] *= -1
            print('negative / index', index, numbers)
            dfs(index + 1)

        else:
            if sum(numbers) == target:
                nonlocal total
                total += 1
                print('matched / index', index, numbers)

    dfs()

    return total

但是,我想知道它是如何運行的,控制台日志也是如此。

positive / index 0 [1, 1, 1, 1, 1]
positive / index 1 [1, 1, 1, 1, 1]
positive / index 2 [1, 1, 1, 1, 1]
positive / index 3 [1, 1, 1, 1, 1] 
positive / index 4 [1, 1, 1, 1, 1]
negative / index 4 [1, 1, 1, 1, -1]
matched / index 5 [1, 1, 1, 1, -1]
negative / index 3 [1, 1, 1, -1, -1] ### how come this index all of sudden becomes 3? ###
positive / index 4 [1, 1, 1, -1, -1]
                ...

我有點理解遞歸索引的增量直到匹配/索引 5 但不太確定為什么下次它變成 3。

日志格式可能會讓您感到困惑。 5 之后,不再進行遞歸調用,因此下一個打印行與舊堆棧幀相關聯,該堆棧幀在探索下一個遞歸調用鏈之前一直在等待其子級解析。

如果添加縮進,您將更清楚地看到父子關系:

print("  " * index + 'positive', numbers)
0 1 2 3 4 5     stack depth
===========================
positive [1, 1, 1, 1, 1]
  positive [1, 1, 1, 1, 1]
    positive [1, 1, 1, 1, 1]
      positive [1, 1, 1, 1, 1]
        positive [1, 1, 1, 1, 1]
        negative [1, 1, 1, 1, -1]
          matched [1, 1, 1, 1, -1]
      negative [1, 1, 1, -1, -1]  <-- here's the call you asked about
      ... calls continue ...

在這里,您可以看到您的問題所涉及的否定分支回到了深度 3 並且不是matched的子分支。 matched調用之后,沒有更多的子節點要探索,堆棧彈出回到父節點,父節點也沒有進一步的節點要探索,並在深度 2 彈出回到它的父節點,它仍然有它的negative子調用鏈要探索,它確實產生了對深度 3 的第二次調用。

暫無
暫無

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

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