某实验室计算机待处理任务以 [start,end,period]
格式记于二维数组 tasks
,表示完成该任务的时间范围为起始时间 start
至结束时间 end
之间,需要计算机投入 period
的时长,注意:
period
可为不连续时间- 首尾时间均包含在内
处于开机状态的计算机可同时处理任意多个任务,请返回电脑最少开机多久,可处理完所有任务。
示例 1:
输入:
tasks = [[1,3,2],[2,5,3],[5,6,2]]
输出:
4
解释: tasks[0] 选择时间点 2、3; tasks[1] 选择时间点 2、3、5; tasks[2] 选择时间点 5、6; 因此计算机仅需在时间点 2、3、5、6 四个时刻保持开机即可完成任务。
示例 2:
输入:
tasks = [[2,3,1],[5,5,1],[5,6,2]]
输出:
3
解释: tasks[0] 选择时间点 2 或 3; tasks[1] 选择时间点 5; tasks[2] 选择时间点 5、6; 因此计算机仅需在时间点 2、5、6 或 3、5、6 三个时刻保持开机即可完成任务。
提示:
2 <= tasks.length <= 10^5
tasks[i].length == 3
0 <= tasks[i][0] <= tasks[i][1] <= 10^9
1 <= tasks[i][2] <= tasks[i][1]-tasks[i][0] + 1
解法1:贪心 + 二分查找 + 栈
同类题目详解:LeetCode 2589. 完成所有任务的最少时间-CSDN博客
Java版:
class Solution {
public int processTasks(int[][] tasks) {
Arrays.sort(tasks, (a, b) -> a[1] - b[1]);
List<int[]> stack = new ArrayList<>();
stack.add(new int[]{-1, -1, 0});
for (int[] task : tasks) {
int start = task[0];
int end = task[1];
int duration = task[2];
int k = binarySearch(stack, start);
duration -= stack.get(stack.size() - 1)[2] - stack.get(k)[2];
if (start <= stack.get(k)[1]) {
duration -= stack.get(k)[1] - start + 1;
}
if (duration <= 0) {
continue;
}
while (stack.size() > 1 && end - stack.get(stack.size() - 1)[1] <= duration) {
duration += stack.get(stack.size() - 1)[1] - stack.get(stack.size() - 1)[0] + 1;
stack.remove(stack.size() - 1);
}
stack.add(new int[]{end - duration + 1, end, stack.get(stack.size() - 1)[2] + duration});
}
return stack.get(stack.size() - 1)[2];
}
private int binarySearch(List<int[]> stack, int target) {
int l = 0;
int r = stack.size() - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (stack.get(mid)[0] < target) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return r;
}
}
Python3版:
class Solution:
def processTasks(self, tasks: List[List[int]]) -> int:
tasks.sort(key = lambda x: x[1])
stack = [[-1, -1, 0]]
for start, end, duration in tasks:
k = bisect_left(stack, start, key = lambda x: x[0])
duration -= stack[-1][2] - stack[k - 1][2]
if start <= stack[k - 1][1]:
duration -= stack[k - 1][1] - start + 1
if duration <= 0:
continue
while len(stack) > 1 and end - stack[-1][1] <= duration:
duration += stack[-1][1] - stack[-1][0] + 1
stack.pop()
stack.append([end - duration + 1, end, stack[-1][2] + duration])
return stack[-1][2]
复杂度分析
- 时间复杂度:O(nlogn),其中 n 为 tasks 的长度。
- 空间复杂度:O(n)。