本来想在LeetCode写题解,没想到验证码一直收不到,那还是记录在这吧
题目见LeetCode 1353题
这个题目本身不是很难,就是要每天参加一个会议,然后看最多能参加几个会议。问题是现在多了超时限制,而增加了些题目难度。
解法一
最先想到的解法肯定是暴力解法,按照会议的结束时间排序,然后每个会议都尝试在某一天去开会,如果可以,那就把这天标记掉,然后结果加1.详细见代码:
public static int maxEvents(int[][] events) {
if (events == null) return 0;
int length = events.length;
if (length <= 1) return length;
Arrays.sort(events, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return (o1[1] == o2[1]) ? (o1[0] - o2[0]) : o1[1] - o2[1];
}
});
int ans = 0;
//重点在于一天只能参加一个会议,开始到结束表示的是这个会议的持续时间!!!
//重点在于哪天参加哪个会议,应该是以结束时间作为基准,因为会议结束了就不能再参加了,那就从空闲时间里挑一个早的时间
//用一个Boolean数组,来存储每一天的状态,当天有没有参加会议,有的话为true,那当天就不能再参加别的会议了。
boolean[] visited = new boolean[events[events.length - 1][1] + 1];
for (int i = 0; i < length; i++) {
int start = events[i][0];
int end = events[i][1];
for (int j = start; j <= end; j++) {
if (!visited[j]) {
ans++;
visited[j] = true;
break;
}
}
}
return ans;
}
根据之前说的,显而易见,这个方法是超时的。也就是LeetCode不允许使用该方法。我当时没多想,以为是数组太多,将天从Boolean改成hashset存储,结果也不行。
那明显,我们是无法存储所有会议是哪天参加这个信息的。
针对这个问题,可以采用优胜劣汰的思路,对于已经决定了哪天参加的会议,我们就抛弃掉这部分信息,只记录参加的场次。这样内存使用会大大下降。
下面的解法二,就使用了最小堆来辅助。
(为什么要先参加结束得最早的会议呢,当然是因为curDay在变大,结束时间限制了会议能被参加的时间底线)
public static int maxEvents3(int[][] events) {
if (events == null) return 0;
int length = events.length;
if (length <= 1) return length;
Arrays.sort(events, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return (o1[0] == o2[0]) ? o1[1] - o2[1] : (o1[0] - o2[0]);
}
});
int ans = 0;
int curDay = events[0][0];
int index = 0;
PriorityQueue<Integer> queue = new PriorityQueue<>();//这个最小堆里存储curDay当天开始的会议的结束时间,如果在这天之前的都给删掉
while (index < length || !queue.isEmpty()) {
//进来之后先把当天之前的数据删掉,因为不能再参加了
while (!queue.isEmpty() && queue.peek() < curDay) {
queue.poll();
}
//接下来把能参加的都加进来
while (index < length && events[index][0] == curDay) {
queue.add(events[index++][1]);
}
//这时候呢,就应该取一个最早结束的会议参加下
if (!queue.isEmpty()) {
queue.poll();
ans++;
}
//每参加一个会议,就过一天,curDay+1
curDay++;
}
return ans;
}
使用最小堆只存放会议开始时间大于等于当前天数的,只要有一条符合记录的数据,我们就可以参加一个会议(会议以结束时间存放在最小堆中),先参加的会议,肯定是结束最早的。