↓快轉到主要內容
  1. LeetCode/

LeetCode 2858: Minimum Edge Reversals So Every Node Is Reachable

·1 分鐘· ·
LeetCode Hard Dynamic-Programming Depth-First-Search Breadth-First-Search Graph
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2026-10-31

  • 提交紀錄:Accepted ×2

解題思路
#

邊是有方向的,但把方向拿掉之後是一棵樹。從節點 i 能走到所有點,等於所有邊都要「從 i 往外指」。所以 ans[i] 是以 i 為根時,指向根方向(往上)的邊數。

每個點都算一次是 O(n^2)。用換根 DP(和 LC 834 一樣):

  1. 以 0 為根 BFS,數有幾條邊是「小孩指向父節點」,這就是 ans[0]。
  2. 根從 p 移到小孩 v 時,只有 p–v 這條邊的需求會改變:
    • 原本是 p → v(順向):以 v 為根時它變成往上指,要多翻一條,ans[v] = ans[p] + 1。
    • 原本是 v → p(逆向):以 p 為根要翻,以 v 為根就不用了,ans[v] = ans[p] - 1。

用 set 存原本的有向邊,查一條邊是不是順向。

我的嘗試
#

兩次都一次通過(10-31 寫了一次,下午又重寫一次)。

正確解法
#

class Solution:
    def minEdgeReversals(self, n: int, edges: List[List[int]]) -> List[int]:
        graph = defaultdict(list)
        for u, v in edges:
            graph[u].append(v)
            graph[v].append(u)
        forward = {(u, v) for u, v in edges}

        parent = [-1] * n
        seen = [False] * n
        seen[0] = True
        order = []
        queue = deque([0])
        while queue:
            node = queue.popleft()
            order.append(node)
            for nei in graph[node]:
                if not seen[nei]:
                    seen[nei] = True
                    parent[nei] = node
                    queue.append(nei)

        ans = [0] * n
        ans[0] = sum(1 for v in order[1:] if (parent[v], v) not in forward)
        for v in order[1:]:
            p = parent[v]
            ans[v] = ans[p] + (1 if (p, v) in forward else -1)
        return ans

複雜度
#

時間 O(n),空間 O(n)。

要特別避免的錯誤
#

  • 換根要照 BFS 順序由上往下,ans[p] 要先算好。
  • 建圖要加兩個方向,不然從 0 走不到只能逆著走的點。

面試口說整理
#

拿掉方向是一棵樹,從 i 走到所有點就是所有邊都要從 i 往外指,所以答案是以 i 為根時往上指的邊數。我先以 0 為根數出來,再換根:根從 p 移到 v,只有這條邊會變,原本 p → v 就加一,v → p 就減一。時間 O(n)。

相關文章

LeetCode 834: Sum of Distances in Tree
·2 分鐘
LeetCode Hard Dynamic-Programming Tree Depth-First-Search Graph Dp-on-Trees
LeetCode 834 解題筆記:換根 DP:先以 0 為根算子樹大小和 ans[0],再用 ans[child] = ans[parent] - size + (n - size) 推到每個節點
LeetCode 968: Binary Tree Cameras
·1 分鐘
LeetCode Hard Dynamic-Programming Tree Depth-First-Search Binary-Tree Dp-on-Trees
LeetCode 968 解題筆記:後序貪心,每個節點三種狀態:有相機、被覆蓋、沒被覆蓋;有小孩沒被覆蓋才放相機,最後根沒被覆蓋要補一台
LeetCode 297: Serialize and Deserialize Binary Tree
·1 分鐘
LeetCode Hard String Tree Depth-First-Search Breadth-First-Search Design Binary-Tree
LeetCode 297 解題筆記:前序遍歷加上空節點標記就能唯一還原樹;反序列化用迭代器依序取值
LeetCode 124: Binary Tree Maximum Path Sum
·1 分鐘
LeetCode Hard Dynamic-Programming Tree Depth-First-Search Binary-Tree Dp-on-Trees
LeetCode 124 解題筆記:DFS 回傳往下的一條鏈,在每個節點用「左鏈 + 自己 + 右鏈」更新答案;負的鏈要丟掉
LeetCode 2973: Find Number of Coins to Place in Tree Nodes
·2 分鐘
LeetCode Hard Dynamic-Programming Tree-Dp Depth-First-Search Sorting Heap Tree
LeetCode 2973 解題筆記:三個數的最大乘積只可能是「最大的三個」或「最小的兩個 × 最大的一個」;每個子樹只回傳最小 2 個和最大 3 個,後序合併
LeetCode 1373: Maximum Sum BST in Binary Tree
·1 分鐘
LeetCode Hard Dynamic-Programming Tree-Dp Binary-Search-Tree Depth-First-Search Tree
LeetCode 1373 解題筆記:後序遍歷回傳 (總和, 最小值, 最大值, 是不是 BST);左子樹的最大值 < 自己 < 右子樹的最小值才是 BST