###### tags: `107 Binary Tree Level Order Traversal II`
# 107 Binary Tree Level Order Traversal II 筆記
## 題目:Given the root of a binary tree, return *the bottom-up level order traversal of its nodes' values*
. (i.e., from left to right, level by level from leaf to root).
**Constraints:**
- The number of nodes in the tree is in the range `[0, 2000]`.
- `1000 <= Node.val <= 1000`
先搞懂題目的意思才能開始解題
### 找了一下資料發現原來 Binary Trhttps://hackmd.io/PoY2WlQwQ_2M2hxSpNOfjg?both#ee Traversal 有好幾種,分別有:
- Preorder Traversal
- Inorder Traversal
- Postorder Traversal
- Level-order Traversal **(這個就是題目要用的方法)**
### 範例
```mermaid
flowchart TB
Root((1))
Root --- Node1
Node1((2))
Root --- Leaf3
Leaf3((3))
Node1 --- Leaf1
Leaf1((4))
Node1 --- Leaf2
Leaf2((5))
```
1. Preorder Traversal: 順序會是根節點、左子節點、右子節點
`[1, 2, 4, 5, 3]`
2. Inorder Traversal: 順序會是左子節點、根節點、右子節點
`[4, 2, 5, 1, 3]`
3. Postorder Traversal: 順序會是左子節點、右子節點、根節點
`[4, 5, 2, 3, 1]`
4. Level-order Traversal: 順序會是從根節點一層一層往下,由左而右
`[1, 2, 3, 4, 5]`
---
## 思路
知道題目意思後就比較好解了,他是一層一層往下但又有點不一樣,他是從最下面那層開始的,那其實還是可以把他從上到下先記錄起來後再翻轉順序就好了。
從 root 開始就把它記錄在 output: [[Int]] 裡面,往下找的時候就順便紀錄 Level 當作 Index 來使用,他是從左而右所以找的時候要從左邊開始,遇到就紀錄在 output 裡面,這樣歷遍完後就會是正常的 Lever-order Traversal,然後再 reverse output 就好了。
## Level Order Traversal
```swift
func levelOrderBottom(_ root: TreeNode?) -> [[Int]] {
var queue: [TreeNode?] = []
var result: [[Int]] = []
guard let root = root else { return [] }
queue.append(root)
traverse(queue: queue, result: &result)
return result.reversed()
}
private func traverse(queue: [TreeNode?], result: inout [[Int]]) {
var nextQueue: [TreeNode?] = []
guard !queue.isEmpty else { return }
result.append(queue.compactMap { $0?.value })
for node in queue {
guard let node = node else { continue }
if let leftNode = node.left {
nextQueue.append(leftNode)
}
if let rightNode = node.right {
nextQueue.append(rightNode)
}
}
traverse(queue: nextQueue, result: &result)
}
```
## Inorder Traversal With HashTable
```swift
private func inOrderTraversal(root: TreeNode?, level: Int = 1, result: inout [Int: [Int]], depth: inout Int) {
guard let root = root else { return }
depth = max(level, depth-1)
if let left = root.left {
if result[level] == nil {
result[level] = [left.val]
} else {
result[level]?.append(left.val)
}
inOrderTraversal(root: left, level: level + 1, result: &result, depth: &depth)
}
if let right = root.right {
if result[level] == nil {
result[level] = [right.val]
} else {
result[level]?.append(right.val)
}
inOrderTraversal(root: right, level: level + 1, result: &result, depth: &depth)
}
}
func levelOrderBottom(_ root: TreeNode?) -> [[Int]] {
guard let root = root else { return [] }
var levelDict: [Int: [Int]] = [0: [root.val]]
var depth: Int = 0
inOrderTraversal(root: root, result: &levelDict, depth: &depth)
var result = [[Int]]()
while depth >= 0 {
result.append(levelDict[depth]!)
depth -= 1
}
return result
}
```
---
## 心得
題目真的要先看清楚再開始思考怎麼做,不然很可能會白做工!一開始看 leetcode 給的範例,還以為是要把兩個兩個節點放在一個 array 裡面,了解題目後才發現原來是把同一層的放在一起的意思。
其實做題目的時候花最多時間的地方是在怎麼建立 Input ,因為我是先在 Playground 裡面做的,所以不會有 input 準備好給我測試,所以花了很多時間在建立 Binary Tree,反而解題用的時間比較短。
---
[作業](https://github.com/GametreeRoger/LeetCode/blob/main/LeetCode107.playground/Contents.swift)