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

LeetCode 1235: Maximum Profit in Job Scheduling

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

基本資料
#

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

  • 提交紀錄:WA ×3 → MLE ×2 → TLE → AC

解題思路
#

工作依結束時間排序,best[j] = 只考慮前 j 個工作的最大收益(best[0] = 0)。第 j 個工作:

  • 不選:best[j - 1]。
  • 選:它開始前結束的工作才能一起選。用二分搜尋找最後一個 end <= start 的工作 i,best[i] + profit。

best 是非遞減的,所以「最後一個 end <= start」就是那些工作裡最好的。

我的嘗試
#

這題我一開始想用時間當 DP 的 index:dp[t] = 時間 t 之前的最大收益。

版本問題
第一版 WA每個時間點只處理了一個在那時結束的工作。例如兩個工作都在時間 7 結束,收益分別是 1 和 9,只處理到收益 1 的那個,回傳 1,答案是 9
第二、三版 WA改成 while 處理同時結束的所有工作,但每個都寫 dp[i] = max(dp[i - 1], ...),後面的工作把前面的結果蓋掉了。例如 startTime = [4, 1, 1]、endTime = [5, 3, 5]、profit = [1, 9, 4]:選 [1, 3] 和 [4, 5] 是 10,回傳 9
兩次 MLE修好覆蓋的問題,但 dp 陣列的長度是最大的結束時間,到 10^9
TLE改用字典存,但還是一個時間點一個時間點跑迴圈
AC改成以工作為單位,排序後二分搜尋

正確解法
#

from bisect import bisect_right

class Solution:
    def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
        jobs = sorted(zip(endTime, startTime, profit))
        ends, best = [0], [0]                      # best[j]:只用前 j 個工作
        for e, s, p in jobs:
            i = bisect_right(ends, s) - 1          # 最後一個 end <= s
            best.append(max(best[-1], best[i] + p))
            ends.append(e)
        return best[-1]

複雜度
#

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

要特別避免的錯誤
#

  • 用時間當 index:時間到 10^9。
  • 同時結束的工作,更新時要跟目前的值取 max,不能直接覆蓋。
  • 題目允許「結束在 X、下一個在 X 開始」,所以是 end <= start,用 bisect_right。

面試口說整理
#

我把工作依結束時間排序,best[j] 是只用前 j 個工作的最大收益。第 j 個工作不選就是 best[j - 1],選的話用二分搜尋找最後一個在它開始前結束的工作,加上它的收益。best 是非遞減的,所以那個位置就是最好的。時間 O(n log n)。

相關文章

LeetCode 1402: Reducing Dishes
·1 分鐘
LeetCode Hard Dynamic-Programming Greedy Sorting Array
LeetCode 1402 解題筆記:排序後從滿意度大的開始選;每多選一道放在最前面,前面選的都往後一格,總和增加「目前選的滿意度總和」,總和是正的就繼續選
LeetCode 2968: Apply Operations to Maximize Frequency Score
·1 分鐘
LeetCode Hard Sliding-Window Sorting Prefix-Sum Binary-Search Array
LeetCode 2968 解題筆記:排序後,把一段全部變成同一個值,最省的目標是中位數;用前綴和 O(1) 算花費,花費隨視窗變大而變大,可以滑動
LeetCode 2141: Maximum Running Time of N Computers
·1 分鐘
LeetCode Hard Greedy Binary-Search Sorting
LeetCode 2141 解題筆記:比平均時間還大的電池只能給一台電腦用,連同那台電腦一起拿掉,剩下的取平均;要用嚴格的大於
LeetCode 1335: Minimum Difficulty of a Job Schedule
·1 分鐘
LeetCode Hard Dynamic-Programming Interval-Dp Array
LeetCode 1335 解題筆記:切成 d 段的分割 DP;dp(i, k) = 從第 i 個工作開始、剩 k 天的最小難度,枚舉今天做到哪裡,邊枚舉邊更新今天的最大難度
LeetCode 312: Burst Balloons
·1 分鐘
LeetCode Hard Dynamic-Programming Interval-Dp Array
LeetCode 312 解題筆記:枚舉區間 (i, j) 裡「最後一個」戳破的氣球 k,這時它的鄰居就是 i 和 j,左右兩邊的子問題互相獨立
LeetCode 1537: Get the Maximum Score
·2 分鐘
LeetCode Hard Dynamic-Programming Two-Pointers Greedy Array
LeetCode 1537 解題筆記:兩個排序陣列只在共同的值可以換路;雙指針合併,兩條路各自累加,遇到共同的值時兩邊都取較大的那個再加上它