leetcode
leetcode 2901 ~ 2950
批量处理任务

批量处理任务

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 501 ms, 内存: 70.3 MB


/*
题目思路:
1. 将所有任务根据结束时间进行排序。
2. 使用一个Set来记录已经选择的时间点。
3. 遍历每一个任务,通过Stream的filter和limit方法选择合适的时间点。
4. 返回最终选择的时间点数量。
*/
import java.util.*;
import java.util.stream.*;

public class TaskSchedulerStream {
    public int minTime(int[][] tasks) {
        Arrays.sort(tasks, (a, b) -> a[1] - b[1]); // 按结束时间排序
        Set<Integer> chosenTimes = new HashSet<>();
        for (int[] task : tasks) {
            int start = task[0], end = task[1], period = task[2];
            List<Integer> availableTimes = IntStream.rangeClosed(start, end)
                    .boxed()
                    .sorted(Comparator.reverseOrder())
                    .filter(time -> !chosenTimes.contains(time))
                    .limit(period)
                    .collect(Collectors.toList());
            chosenTimes.addAll(availableTimes);
        }
        return chosenTimes.size();
    }

    public static void main(String[] args) {
        TaskSchedulerStream scheduler = new TaskSchedulerStream();
        int[][] tasks = {{1, 3, 2}, {2, 5, 3}, {5, 6, 2}};
        System.out.println(scheduler.minTime(tasks)); // 输出:4
    }
}

解释

方法:

该题解利用了排序和栈的结构来解决问题。首先,将任务按照结束时间进行排序,这样可以按顺序处理每个任务,并尽可能地减少开机时间。使用一个栈来存储已经处理的时间段,栈中的元素形式为(start, end, total),其中start和end表示当前连续的开机时间段,total是截至当前时间的总开机时间。对每个任务,算法尝试将它的运行时间安排在已有的时间段中,如果现有时间段不足以满足任务的需求,则从任务的结束时间向前扩展新的时间段。通过这样的处理,可以确保每个任务在其允许的时间范围内得到处理,并且总的开机时间是最短的。

时间复杂度:

O(n log n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在栈中使用了一个哨兵元素(-2, -2, 0),它在算法中具体起到了什么作用?
在栈中使用哨兵元素(-2, -2, 0)主要是为了处理栈为空的情况,避免在执行栈操作时需要额外的条件判断。哨兵元素确保栈至少有一个元素,这样在使用例如`stack[-1]`或在执行`bisect_left`查找时,可以保证始终有元素可参与比较,从而简化代码逻辑。此外,哨兵的值被设定为负数和0,这些值在实际任务时间范围之外,保证它不会影响到任务的处理和时间计算。
🦆
代码中存在`while end - stack[-1][1] <= d`的循环判断,该循环的目的是什么?在什么情况下会结束循环?
这个循环的目的是处理当前任务所需的额外开机时间。循环会检查栈顶的时间段是否足够覆盖当前任务需要的剩余时间。如果栈顶的时间段(从其结束时间`stack[-1][1]`到任务的结束时间`end`)不足以提供所需的时间`d`,则循环会弹出这个时间段,并将其时间加回到`d`中,即继续寻找或扩展更多的时间来满足任务需求。循环会在找到足够的时间覆盖所需的`d`,或是当栈中没有更多可用的时间段时结束。这确保了每个任务都在其允许的时间内被处理,同时尽可能减少开机时间。

相关问题