LeetCode-2589. 完成所有任務的最少時間【棧 貪心 數組 二分查找 排序】
- 題目描述:
- 解題思路一:貪心+暴力
- 解題思路二:棧+二分查找
- 解題思路三:簡化版
題目描述:
你有一臺電腦,它可以 同時 運行無數個任務。給你一個二維整數數組 tasks ,其中 tasks[i] = [starti, endi, durationi] 表示第 i 個任務需要在 閉區間 時間段 [starti, endi] 內運行 durationi 個整數時間點(但不需要連續)。
當電腦需要運行任務時,你可以打開電腦,如果空閑時,你可以將電腦關閉。
請你返回完成所有任務的情況下,電腦最少需要運行多少秒。
示例 1:
輸入:tasks = [[2,3,1],[4,5,1],[1,5,2]]
輸出:2
解釋:
- 第一個任務在閉區間 [2, 2] 運行。
- 第二個任務在閉區間 [5, 5] 運行。
- 第三個任務在閉區間 [2, 2] 和 [5, 5] 運行。
電腦總共運行 2 個整數時間點。
示例 2:
輸入:tasks = [[1,3,2],[2,5,3],[5,6,2]]
輸出:4
解釋:
- 第一個任務在閉區間 [2, 3] 運行
- 第二個任務在閉區間 [2, 3] 和 [5, 5] 運行。
- 第三個任務在閉區間 [5, 6] 運行。
電腦總共運行 4 個整數時間點。
提示:
1 <= tasks.length <= 2000
tasks[i].length == 3
1 <= starti, endi <= 2000
1 <= durationi <= endi - starti + 1
解題思路一:貪心+暴力
三個關鍵點。1. 按區間右端點排序。2. 把任務盡可能安排在區間的后綴。3. 用數組記錄任務的執行情況
class Solution:def findMinimumTime(self, tasks: List[List[int]]) -> int:tasks.sort(key = lambda x: x[1]) # 排序run = [False] * (tasks[-1][1] + 1) # 初始化確定哪些時間運行的數組for s, e, d in tasks:d -= sum(run[s: e + 1]) # 去掉運行中的時間點if d <= 0: # 該任務已完成continuefor i in range(e, s-1, -1): # 標記需要運行的時間點if run[i]:continuerun[i] = Trued -= 1if d == 0:breakreturn sum(run)
時間復雜度:O(nM)其中 n 是 tasks 的大小,M 是 tasks 的時間段右端點 end 的最大值。
空間復雜度:O(logn + M) 排序和記錄的數組
解題思路二:棧+二分查找
class Solution:def findMinimumTime(self, tasks: List[List[int]]) -> int:tasks.sort(key=lambda t: t[1])# 棧中保存閉區間左右端點,棧底到棧頂的區間長度的和st = [(-2, -2, 0)] # 哨兵,保證不和任何區間相交for start, end, d in tasks:_, r, s = st[bisect_left(st, (start,)) - 1]d -= st[-1][2] - s # 去掉運行中的時間點if start <= r: # start 在區間 st[i] 內d -= r - start + 1 # 去掉運行中的時間點if d <= 0:continuewhile end - st[-1][1] <= d: # 剩余的 d 填充區間后綴l, r, _ = st.pop()d += r - l + 1 # 合并區間st.append((end - d + 1, end, st[-1][2] + d))return st[-1][2]
時間復雜度:O(nlogn)
空間復雜度:O(n)
解題思路三:簡化版
class Solution:def findMinimumTime(self, tasks: List[List[int]]) -> int:tasks.sort(key = lambda x: x[1])run = [False] * (tasks[-1][1] + 1)for s, e, d in tasks:d -= sum(run[s: e + 1]) # 先減去已經運行的時間if d <= 0: # 已經okcontinuefor i in range(e, s - 1, -1): # 還沒okif run[i]:continuerun[i] = Trued -= 1if d == 0:breakreturn sum(run)
時間復雜度:O(nM)其中 n 是 tasks 的大小,M 是 tasks 的時間段右端點 end 的最大值。
空間復雜度:O(logn + M) 排序和記錄的數組

? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ? ⊕ ?