算法面試套路|深度優先搜索(Depth-First Search, DFS)
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
本篇內容主要為 Grokking the Coding Interview: Patterns for Coding Questions 的翻譯與整理,行有餘力建議可以購買該專欄課程閱讀並在上面進行練習。
重點整理
- 深度優先搜索(Depth-First Search, DFS)
- 策略:使用 遞迴(recursion) 或透過 堆棧(stack) 追蹤遍歷過程的父節點
- 題型:
題目匯總
0018
Diameter of a Binary Tree
0020
Lowest Common Ancestor of a Binary Tree
0100
Same Tree
0104
Maximum Depth of Binary Tree
0110
Balanced Binary Tree
0111
Minimum Depth of Binary Tree
0112
Path Sum
0113
Path Sum II
0129
Sum Root to Leaf Numbers
0133
Clone Graph
0200
Number of Islands
0257
Binary Tree Paths
0437
Path Sum III
0897
Increasing Order Search Tree
[例題] Binary Tree Path Sum
問題
給定一棵二元樹(binary tree)與一個數字 ,找出該二元樹中是否存在一條自根節點到葉子節點的路徑,滿足路徑上節點數值總和恰好等於 。
Example 01
說明 |
二元樹 |
|
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
|
Example 02
陣列 |
二元樹 |
|
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
|
題解
由於我們想要 搜索自根結點到葉子節點的路徑,因此採用 深度優先搜索(Depth-First Search, DFS) 技巧。
為了遞迴遍歷二元樹,我們可以自根節點開始,呼叫兩個遞迴函數分別處理左子節點和右子節點。具體演算法的步驟如下:
- 自根結點
root
開始進行深度優先搜索
- 如果當前節點並不是葉子節點,進行以下操作:
- 將路徑和減去當前節點的值,即
S = S - node.val
- 呼叫遞迴函數,處理當前節點的左子節點和右子節點,注意子節點須滿足的路經和為前一步驟所得到的
S = S - node.val
- 如果當前節點是葉子節點,且其值滿足路徑和 ,即找到滿足條件的路徑,返回
true
- 如果當前節點是葉子節點,但其值不滿足路徑和 不同,返回
talse
上述步驟如下圖所示:
1. 自根結點 root
開始進行深度優先搜索
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
2. 當前節點並非葉子節點,呼叫遞迴函數處理左右子節點,遞迴時 S = 23 - 12 = 11
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
3. 當前節點並非葉子節點,呼叫遞迴函數處理左右子節點,遞迴時 S = 11 - 7 = 4
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
4. 當前節點已為葉子節點,但不滿足 S = 9
,故返回 false
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
5. 節點 7
的左子樹遞迴遍歷完畢,遍歷右子樹;由於右子樹為 null
,故返回 false
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
6. 節點 12
的左子樹遞迴遍歷完畢,遍歷右子樹,遞迴時 S = 23 - 12 = 11
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
7. 當前節點並非葉子節點,呼叫遞迴函數處理左右子節點,遞迴時 S = 11 - 1 = 10
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
8. 當前節點已為葉子節點,並且滿足 S = 10
,故返回 true
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
9. 左子節點滿足條件,返回 true
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
10. 右子節點滿足條件,返回 true
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
代碼
C++
Java
JavaScript
Python
分析
- 時間複雜度:,其中 為二元樹中的節點總數
- 空間複雜度:,該空間被用來儲存遞迴堆棧(recursion stack),最糟狀況是當給定二元樹為一個鏈表時,即所有節點都只有一個子節點
[例題] All Paths for a Sum
問題
給定一棵二元樹(binary tree)與一個數字 ,找出該二元樹中所有自根節點到葉子節點總和等於 的路徑。
Example 01
說明 |
二元樹 |
|
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
|
Example 02
說明 |
二元樹 |
|
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
|
題解
這一題遵循 深度優先搜索(Depth-First Search, DFS) 策略,注意以下幾點:
- 每次找到滿足條件的路徑時,將其儲存於一個陣列中
- 我們需要遍歷所有路徑,不能在找到第一條路徑時就停止搜索
代碼
C++
Java
JavaScript
Python
分析
- 時間複雜度:,其中 為二元樹中的節點總數;遍歷所有節點需要花費 ,而在每個葉子節點,需要複製 個結點來儲存其路徑
- 空間複雜度:,其中需要 儲存遞迴堆棧(recursion stack);而儲存所有路徑需要
- 對於二元樹而言,每個葉子節點只有一條路徑可以到達,亦即路徑總數不超過葉子節點數量,因此最大元素數為
- 每一條路徑包含多個節點,對於平衡二元樹來說,每個葉子節點都位在最大深度,而平衡二元樹的深度是
[例題] Sum of Path Numbers
問題
給定一棵二元樹(binary tree),其中節點的值只可能為 0 - 9
,每一條路徑代表一個數字,計算所有數字的總和。
Example 01
說明 |
二元樹 |
|
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
|
Example 02
說明 |
二元樹 |
|
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
|
題解
這一題遵循 深度優先搜索(Depth-First Search, DFS) 策略,在過程中需要 追蹤當前路徑表示的數字。
那麼我們要如何計算目前路徑所代表的數字呢?比如前面範例中,我們正處在 7
這個節點時,當前路徑所代表的數字為 17 = 1x10 + 7
。
代碼
C++
Java
JavaScript
Python
分析
- 時間複雜度:,其中 為二元樹中的節點總數
- 空間複雜度:,該空間被用來儲存遞迴堆棧(recursion stack),最糟狀況是當給定二元樹為一個鏈表時,即所有節點都只有一個子節點
[例題] Path with Given Sequence
問題
給定一棵二元樹(binary tree)與一個整數陣列,判斷該整數陣列是不是樹中的一條路徑。
Example 01
說明 |
二元樹 |
|
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
|
Example 02
說明 |
二元樹 |
|
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
|
題解
這一題遵循 深度優先搜索(Depth-First Search, DFS) 策略,在過程中需要 判斷當前數值是否與陣列元素相符,一但不滿足可以儘早返回。
代碼
C++
Java
JavaScript
Python
分析
- 時間複雜度:,其中 為二元樹中的節點總數
- 空間複雜度:,該空間被用來儲存遞迴堆棧(recursion stack),最糟狀況是當給定二元樹為一個鏈表時,即所有節點都只有一個子節點
[例題] Count Paths for a Sum
問題
給定一棵二元樹(binary tree)與一個數字 ,找出該二元樹中所有總和等於 的路徑,注意此處的路徑並 不要求自根結點到葉子節點,只需要遵循父節點到子節點的方向即可。
Example 01
說明 |
二元樹 |
|
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
|
Example 02
說明 |
二元樹 |
|
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
|
題解
這一題遵循 深度優先搜索(Depth-First Search, DFS) 策略,注意以下幾點:
- 必須使用一個陣列追蹤當前路徑,並傳遞給後續的遞迴函數
- 當遍歷一個節點時,需要執行兩件事:
- 添加當前節點到當前路徑中
- 計算路徑陣列中以當前節點為結束元素的路徑和,若滿足 則將計數
count
加一
- 必須遍歷所有路徑,不能在找到條件的路徑時就結束
- 在返回時必須自路徑中移除當前節點,因為還必須遞迴遍歷其他路徑,需要進行回溯(backtrack)
代碼
C++
Java
JavaScript
Python
分析
- 時間複雜度:遍歷所有節點需要 ,每一個節點都必須迭代當前路徑,此時:
- 最差狀況在傾斜樹(skewed tree)時的路徑需要 ,故為
- 最優狀況在平衡樹(balanced tree)時的路徑需要 ,故為
- 空間複雜度:,該空間被用來儲存遞迴堆棧(recursion stack),最糟狀況是當給定二元樹為一個鏈表時,即所有節點都只有一個子節點;除此之外還需要有 儲存
currentPath
。故
參考資料