[LeetCode] 1353. Maximum Number of Events That Can Be Attended

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. Notice that 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.

Example 2:

Input: events= [[1,2],[2,3],[3,4],[1,2]]
Output: 4

Example 3:

Input: events = [[1,4],[4,4],[2,2],[3,4],[1,1]]
Output: 4

Example 4:

Input: events = [[1,100000]]
Output: 1

Example 5:

Input: events = [[1,1],[1,2],[1,3],[1,4],[1,5],[1,6],[1,7]]
Output: 7

Constraints:

  • 1 <= events.length <= 105
  • events[i].length == 2
  • 1 <= startDayi <= endDayi <= 105

最多可以参加的会议数目。给一个数组events,里面包含的是一些events的[startDay, endDay],表示每个event的开始日期和结束日期。你可以在[startDay, endDay]的任何一天去参加这个会议。请你返回你能参加的会议的最大数目。

思路是贪心。这个题看着好像可以用扫描线的思路做,其实是没什么关系的,因为这道题不涉及区间左右边界的比较和尝试找overlap或者gap这一类的操作。正确的思路是你需要一个最小堆存储events的结束时间endDay。首先还是对input排序,这里我们是对events的startDay排序(注意跟最小堆存储内容的不同)。因为会议的结束日期最大可以到100000所以我们从1遍历到100000,意思是从第1天遍历到第100000天,然后去看每一天是否能参加event。

在第d天的时候,

  • 如果此时最小堆不为空且堆顶元素(的结束时间)小于今天的天数d,则意味着我们无法去这个event了,直接从最小堆中弹出即可
  • 此时如果最小堆还有东西,剩下的东西都是一些event的结束时间endDay,且这些结束时间晚于今天的天数d,则弹出一个并且res++,意思是今天可以去其中的一个event
  • 如果有event的startDay是今天,则把他的endDay加入最小堆

时间O(nlogn)

空间O(n)

Java实现

 1 class Solution {
 2     public int maxEvents(int[][] events) {
 3         PriorityQueue<Integer> pq = new PriorityQueue<>();
 4         Arrays.sort(events, (a, b) -> a[0] - b[0]);
 5         int res = 0;
 6         int i = 0;
 7         int n = events.length;
 8         for (int d = 1; d <= 100000; d++) {
 9             // 会议结束时间已经早于今天的,就直接舍弃了,因为没法参加
10             while (!pq.isEmpty() && pq.peek() < d) {
11                 pq.poll();
12             }
13             // 会议开始时间是今天的,把他的结束时间放到pq中
14             while (i < n && events[i][0] == d) {
15                 pq.offer(events[i][1]);
16                 i++;
17             }
18             // 目前pq中的元素都是在今天之前就开始的,并且结束时间 >= 今天
19             if (!pq.isEmpty()) {
20                 pq.poll();
21                 res++;
22             }
23         }
24         return res;
25     }
26 }

 

LeetCode 题目总结

posted @ 2020-09-28 12:40  CNoodle  阅读(835)  评论(0编辑  收藏  举报