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

LeetCode 2973: Find Number of Coins to Place in Tree Nodes

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

基本資料
#

難易度: hard 第一次嘗試:2026-09-12

  • 提交紀錄:Wrong Answer ×3 → Accepted ×2

解題思路
#

子樹裡選三個不同節點的最大乘積,只有兩種可能:

  • 最大的三個相乘。
  • 最小的兩個(可能是兩個負數)× 最大的一個。

所以每個子樹只需要知道最小的 2 個和最大的 3 個,最多 5 個數。後序遍歷:把自己和所有孩子回傳的數合在一起、排序,算答案,再截斷成 5 個往上回傳。

  • 子樹大小 < 3:放 1 個硬幣。
  • 乘積是負的:放 0 個。

邊是無向的,要建雙向的鄰接表,DFS 時記住父節點。

我的嘗試
#

版本問題
第一版用 heap 收集子樹的值,但葉子回傳的是正的 cost,內部節點回傳的是取負號的 heap,正負號混在一起。例如邊 [[0, 1], [1, 2], [0, 3]]、cost = [1, 2, 3, 1]:根的答案是 3 × 2 × 1 = 6,回傳 0
第二版修好正負號,但只拿最大的三個相乘,漏掉兩個負數。例如邊 [[0, 1], [0, 2], [1, 3]]、cost = [6, -5, 0, -4]:6 × (-5) × (-4) = 120,回傳 0
第三版乘積修好,但鄰接表只建了 u → v,假設每條邊都是「父 → 子」。題目的邊沒有方向,例如 [[1, 0]] 這種寫法,節點 0 找不到孩子
AC建雙向的鄰接表,DFS 帶父節點

正確解法
#

class Solution:
    def placedCoins(self, edges: List[List[int]], cost: List[int]) -> List[int]:
        adj = defaultdict(list)
        for u, v in edges:
            adj[u].append(v)
            adj[v].append(u)                       # 邊沒有方向
        res = [0] * len(cost)

        def dfs(node: int, parent: int) -> List[int]:
            vals = [cost[node]]
            for child in adj[node]:
                if child != parent:
                    vals.extend(dfs(child, node))
            vals.sort()
            if len(vals) < 3:
                res[node] = 1
            else:
                res[node] = max(0, vals[-1] * vals[-2] * vals[-3], vals[0] * vals[1] * vals[-1])
            return vals if len(vals) <= 5 else vals[:2] + vals[-3:]   # 只留最小 2 個、最大 3 個

        dfs(0, -1)
        return res

複雜度
#

每個節點合併的數最多是 5 × 孩子數 + 1,排序成本是常數倍,總共 O(n log n) 左右。DFS 深度最多 n(一條鏈時),n = 2 × 10^4 可能要調高遞迴上限或改成迭代。

要特別避免的錯誤
#

  • 只看最大的三個:兩個負數相乘會變正。
  • 正負號在 heap 裡混用。
  • 把邊當成有方向的。

面試口說整理
#

三個數的最大乘積只可能是最大的三個相乘,或最小的兩個乘最大的一個,所以每個子樹只要回傳最小 2 個和最大 3 個。我後序遍歷,把自己和孩子回傳的數合在一起排序算答案,再截斷成 5 個往上傳。邊是無向的,要建雙向鄰接表。時間大約 O(n log n)。

相關文章

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
LeetCode 1425: Constrained Subsequence Sum
·1 分鐘
LeetCode Hard Sliding-Window Dynamic-Programming Monotonic-Queue Heap Queue Array
LeetCode 1425 解題筆記:dp[i] = nums[i] + max(0, 前 k 個 dp 的最大值);前 k 個 dp 的最大值是滑動視窗最大值,用單調佇列 O(1) 取得
LeetCode 1235: Maximum Profit in Job Scheduling
·1 分鐘
LeetCode Hard Dynamic-Programming Binary-Search Sorting Array
LeetCode 1235 解題筆記:工作依結束時間排序,best[j] = 只用前 j 個工作的最大收益;選第 j 個時二分搜尋最後一個結束時間 <= 開始時間的工作
LeetCode 2402: Meeting Rooms III
·2 分鐘
LeetCode Hard Heap Sorting Simulation Intervals
LeetCode 2402 解題筆記:空閒房間和忙碌房間各一個 heap,延後的會議要保留原本的長度
LeetCode 337: House Robber III
·1 分鐘
LeetCode Medium Dynamic-Programming Tree Depth-First-Search Binary-Tree
LeetCode 337 解題筆記:樹上 DP,每個節點回傳(搶它、不搶它)的最大值;不是一層一層交錯搶
LeetCode 987: Vertical Order Traversal of a Binary Tree
·1 分鐘
LeetCode Hard Tree Binary-Tree Bfs Sorting
LeetCode 987 解題筆記:收集 (欄, 列, 值) 三元組,排序後依欄分組