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

LeetCode 2163: Minimum Difference in Sums After Removal of Elements

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

基本資料
#

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

  • 提交紀錄:Accepted(一次通過)

解題思路
#

刪掉 n 個之後,剩下的前 n 個是第一段、後 n 個是第二段。換個角度:選一個分界 k(n <= k <= 2n),第一段從 nums[:k] 裡選 n 個,第二段從 nums[k:] 裡選 n 個。

要讓 sum_first - sum_second 最小:

  • 第一段選 nums[:k] 裡最小的 n 個:從左往右掃,用最大堆維護目前最小的 n 個,多了就把最大的丟掉。left_min[k - 1] = 前 k 個裡最小 n 個的和。
  • 第二段選 nums[k:] 裡最大的 n 個:從右往左掃,用最小堆維護,多了就丟最小的。right_max[k] = 從 k 開始最大 n 個的和。

答案是 min(left_min[k - 1] - right_max[k])。

我的解法
#

import heapq

class Solution:
    def minimumDifference(self, nums: List[int]) -> int:
        n = len(nums) // 3

        left_min = [0] * (3 * n)                   # left_min[i]:nums[:i+1] 最小 n 個的和
        heap, total = [], 0                        # 最大堆(存負數)
        for i in range(2 * n):
            heapq.heappush(heap, -nums[i])
            total += nums[i]
            if len(heap) > n:
                total += heapq.heappop(heap)       # 丟掉最大的(存的是負數)
            left_min[i] = total

        right_max = [0] * (3 * n)                  # right_max[i]:nums[i:] 最大 n 個的和
        heap, total = [], 0                        # 最小堆
        for i in range(3 * n - 1, n - 1, -1):
            heapq.heappush(heap, nums[i])
            total += nums[i]
            if len(heap) > n:
                total -= heapq.heappop(heap)       # 丟掉最小的
            right_max[i] = total

        return min(left_min[k - 1] - right_max[k] for k in range(n, 2 * n + 1))

複雜度
#

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

要特別避免的錯誤
#

  • 分界的範圍是 n 到 2n:兩邊都要至少有 n 個可以選。
  • Python 只有最小堆,最大堆要存負數,彈出來的值也是負的。

面試口說整理
#

刪掉 n 個之後,等於選一個分界,第一段從左邊選 n 個、第二段從右邊選 n 個。要差最小,左邊選最小的 n 個、右邊選最大的 n 個。我從左往右用最大堆算每個前綴的最小 n 個的和,從右往左用最小堆算每個後綴的最大 n 個的和,再枚舉分界。時間 O(n log n)。

相關文章

LeetCode 4041: Minimum Operations to Form Subset Sum II
·2 分鐘
LeetCode Hard Dynamic-Programming Knapsack Breadth-First-Search Array
LeetCode 4041 解題筆記:乘除可以任意順序,用 BFS 找每個數能變成的所有值(不超過 sum)和最少步數,再做跟 4040 一樣的分組 0/1 背包
LeetCode 2585: Number of Ways to Earn Points
·1 分鐘
LeetCode Hard Dynamic-Programming Knapsack Array
LeetCode 2585 解題筆記:有數量上限的背包(分組背包);每種題目選 0 到 count 題,容量倒著走,在裡面枚舉選幾題
LeetCode 410: Split Array Largest Sum
·1 分鐘
LeetCode Hard Dynamic-Programming Binary-Search Greedy Prefix-Sum Array
LeetCode 410 解題筆記:對答案二分搜尋;給定上限 mid,貪心地能塞就塞,數出最少要切幾段,段數 <= k 就表示 mid 可行
LeetCode 2355: Maximum Number of Books You Can Take
·2 分鐘
LeetCode Hard Dynamic-Programming Monotonic-Stack Stack Array
LeetCode 2355 解題筆記:以 i 結尾時往左每格少拿 1 本,直到碰到書比較少的瓶頸書架 j;用單調堆疊找 j,dp[i] = dp[j] + 等差數列和
LeetCode 3989: Maximum Consistent Columns in a Grid
·1 分鐘
LeetCode Hard Dynamic-Programming Matrix Array
LeetCode 3989 解題筆記:保留的欄位是一個子序列,只要相鄰的兩欄相容;LIS 型 DP,dp[j] = 以第 j 欄結尾的最長合法序列
LeetCode 1402: Reducing Dishes
·1 分鐘
LeetCode Hard Dynamic-Programming Greedy Sorting Array
LeetCode 1402 解題筆記:排序後從滿意度大的開始選;每多選一道放在最前面,前面選的都往後一格,總和增加「目前選的滿意度總和」,總和是正的就繼續選