Binary Tree Right Side View

題目描述

給定一棵二元樹的根節點 root,回傳從右側看到的節點值(從上到下排列)。

輸入:     1
         / \
        2   3
         \   \
          5   4
輸出: [1, 3, 4]

輸入:   1
         \
          3
輸出: [1, 3]

解題思路

1

初始化 Queue

將 root 放入 Queue,準備開始逐層遍歷

2

逐層遍歷

用 levelSize = queue.Count 記錄當前層節點數,內層迴圈只處理這麼多個

3

記錄每層最後一個

當 i == levelSize - 1 時,該節點是這一層最右邊的,加入結果列表

4

加入子節點

對每個出隊節點,先加左子再加右子到 Queue,作為下一層的來源

程式碼

C#

csharp
public class Solution {
    public IList<int> RightSideView(TreeNode root) {
        var result = new List<int>();
        if (root == null) return result;
 
        var queue = new Queue<TreeNode>();
        queue.Enqueue(root);
 
        while (queue.Count > 0) {
            int levelSize = queue.Count;
            for (int i = 0; i < levelSize; i++) {
                var node = queue.Dequeue();
                // 每層最後一個節點
                if (i == levelSize - 1) result.Add(node.val);
                if (node.left != null) queue.Enqueue(node.left);
                if (node.right != null) queue.Enqueue(node.right);
            }
        }
        return result;
    }
}

TypeScript

typescript
function rightSideView(root: TreeNode | null): number[] {
    if (!root) return [];
 
    const result: number[] = [];
    const queue: TreeNode[] = [root];
 
    while (queue.length > 0) {
        const levelSize = queue.length;
        for (let i = 0; i < levelSize; i++) {
            const node = queue.shift()!;
            if (i === levelSize - 1) result.push(node.val);
            if (node.left) queue.push(node.left);
            if (node.right) queue.push(node.right);
        }
    }
    return result;
}

Python

python
from collections import deque
 
def rightSideView(root: Optional[TreeNode]) -> list[int]:
    if not root:
        return []
 
    result = []
    queue = deque([root])
 
    while queue:
        level_size = len(queue)
        for i in range(level_size):
            node = queue.popleft()
            if i == level_size - 1:  # 每層最後一個
                result.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
    return result

複雜度分析

| | Time | Space | |--|------|-------| | 本解法 | O(n) | O(w) |

w 是樹的最大寬度,最壞 O(n)。Time O(n) 是因為每個節點恰好入隊出隊一次。Space O(w) 是因為 Queue 同時最多存放一層的所有節點,完全二元樹最底層有 n/2 個節點。

邊界情況

圖解

1 ← 第 0 層可見
2
3 ← 第 1 層可見
5
4 ← 第 2 層可見

圖表展示了三層 BFS 的過程:第 0 層只有 1(可見)、第 1 層有 2 和 3 取最後一個 3(可見)、第 2 層有 5 和 4 取最後一個 4(可見),結果 [1, 3, 4]

進階觀點

💡面試追問

Q: 如何用 DFS 解? A: 用 DFS 先走右子樹再走左子樹,維護 depth 變數。當 depth == result.length 代表這是該層第一次被訪問的節點(因為先走右,所以是最右邊的)。Space 為 O(h) 優於 BFS 的 O(w)。

Q: 如何改成 Left Side View? A: BFS 方案中把條件改為 i == 0(每層第一個元素)。DFS 方案中改為先走左子樹再走右子樹。

變體題:LC 116 Populating Next Right Pointers、LC 102 Binary Tree Level Order Traversal。

理解測驗

🤔 為什麼用 BFS 而不是 DFS 來解這題更直覺?

🤔 如果某層只有左子節點沒有右子節點,右側看到的是哪個?

你可能也想看

236. Lowest Common Ancestor of a Binary Tree1161. Maximum Level Sum of a Binary Tree

按 ← → 鍵切換課程