Maximum Number of Events That Can Be Attended

给定一个数组,其中每个事件都有开始和结束时间。你可以从任何一天开始并结束一个事件,但一次只能参加一个。返回最多可以参加的事件数量。问题可以通过贪心算法解决,按事件开始时间排序,优先选择结束时间最早的事件。

You are given an array of events where events[i] = [startDayi, endDayi]. Every event i starts at startDayi and ends at endDayi.

You can attend an event i at any day d where startTimei <= d <= endTimei. You can only attend one event at any time d.

Return the maximum number of events you can attend.

Example 1:

Input: events = [[1,2],[2,3],[3,4]]
Output: 3
Explanation: You can attend all the three events.
One way to attend them all is as shown.
Attend the first event on day 1.
Attend the second event on day 2.
Attend the third event on day 3.

思路:这题是贪心算法,按照start排序之后,优先做deadline最早的活,扫描day,然后把所有满足trigger event的endday丢入pq中排序。然后把超过today的dueday的event丢掉,每次poll出来一个,然后扫描下一天。nlogn;

class Solution {
    public int maxEvents(int[][] events) {
        Arrays.sort(events, (a, b) -> (a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]));
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
        int i = 0;
        int res = 0;
        for(int day = 1; day <= 100000; day++) {
            while(i < events.length && events[i][0] <= day) {
                pq.offer(events[i][1]);
                i++;
            }
            // 做完之后,要把pq里面,deadline超过今天的全部给踢掉;
            while(!pq.isEmpty() && pq.peek() < day) {
                pq.poll();
            }
            
            if(!pq.isEmpty()) {
                pq.poll();
                res++;
            }
        }
        return res;
    }
}
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int t = sc.nextInt(); int[][] wos = new int[n][2]; for (int i = 0; i < n; i++) { wos[i][0] = sc.nextInt(); wos[i][1] = sc.nextInt(); } System.out.println(getResult(wos, t)); } public static int getResult(int[][] wos, int t) { // 按照任务截止时间升序 Arrays.sort(wos, (a, b) -> a[0] - b[0]); // pq用于按照积分对任务进行优先级排序,积分越小,优先级越高,目的是为了每次替换掉最少积分的工单 PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> a - b); // 当前时间 int curTime = 0; // 已获得的积分 int ans = 0; // 遍历任务 for (int[] wo : wos) { int endTime = wo[0]; // 任务截止时间 int score = wo[1]; // 任务积分 if (curTime < endTime) { // 如果 curTime < 当前任务的截止时间,则curTime时刻可以指向当前任务 pq.offer(score); ans += score; curTime++; } else { // 如果 curTime >= 当前任务的截止时间,则当前任务只能在curTime时刻之前找一个时间点执行 // pq中记录的就是curTime之前时刻执行的任务 if (pq.size() == 0) { continue; } // 此时取出pq记录的可执行的任务中最小积分的那个 int min_score = pq.peek(); // 如果当前任务的积分 > 前面时间内可执行的任务中最小积分 if (score > min_score) { // 则我们应该将执行pq中最小积分任务的时间,用于执行当前任务,因为这样可以获得更大积分 pq.poll(); pq.offer(score); ans += score - min_score; } } } // 由于时间限制为t单位,而每个任务花费1单位时间,因此最多完成t个任务,对于多出任务应该去除,且优先去除积分少的 while (pq.size() > t && t > 0) { ans -= pq.poll(); } return ans; } }
最新发布
12-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值