package com.heu.wsq.leetcode.interval;
import java.util.*;
/**
* 1897 · 会议室 3
* @author wsq
* @date 2021/4/20
* 描述
* 你有一个当前会议列表intervals,里面表明了每个会议的开始和结束时间,以及一些会议室rooms。现在有一系列会议ask需要加入,逐个判断他们能否被安排进当前的会议列表中而不产生冲突。一个会议室在同一时间只能进行一场会议。每个询问都相互独立。
* Ensure that Intervals can be arranged in rooms meeting rooms
* Ensure that the end time of any meeting is not greater than 50000
* |Intervals|<=50000
* |ask|<=50000
* rooms<=20
*
* 样例
* 例 1:
* 输入:
* Intervals:[[1,2],[4,5],[8,10]],rooms = 1,ask: [[2,3],[3,4]]
* 输出:
* [true,true]
*
* 解释:
* 对于[2,3]的询问,我们可以安排一个会议室room0。
* 以下是room0的会议列表:
* [[1,2],[2,3],[4,5],[8,10]]
* 对于[3,4]的询问,我们可以安排一个会议室room0。
* 以下是room0的会议列表:
* [[1,2],[3,4],[4,5],[8,10]]
*
* 链接:https://www.lintcode.com/problem/1897/
*/
public class MeetingRoomIII {
/**
* 这道题太经典,主要是解决了区间判重以及最大重叠区间问题
* 主要思路:
* 1. 按开始时间和结束时间统计对应的数量
* 2. 将两者merge到一起
* 3. 按照时间升序排序
* 4. 直接遍历merge后的列表获取重叠区间个数
* 5. 其余子步骤看注释吧
* @param intervals
* @param rooms
* @param ask
* @return
*/
public boolean[] meetingRoomIII(int[][] intervals, int rooms, int[][] ask) {
// Write your code here.
// 使用map保存,时间以及数量
Map<Integer, Integer> map = new HashMap<>();
for(int[] v: intervals){
map.put(v[0], map.getOrDefault(v[0], 0) + 1);
map.put(v[1], map.getOrDefault(v[1], 0) - 1);
}
// 将开始时间和结束时间归并到一起
List<int[]> list = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry: map.entrySet()){
list.add(new int[]{entry.getKey(), entry.getValue()});
}
// 按照时间升序排序list
Collections.sort(list, new Comparator<int[]>(){
public int compare(int[] o1, int[] o2){
return o1[0] - o2[0];
}
});
int preNum = 0;
List<int[]> pos = new ArrayList<>();
for(int i = 0; i < list.size(); i++){
int[] v = list.get(i);
preNum += v[1];
// rooms一定是满足原来会议进行的
if(preNum == rooms){
// 证明当前会议用完了,所以保存 当前时间 到 下一个时间,
// 这个时间段内没有会议室可用,也就是不能添加会议
pos.add(new int[]{v[0], list.get(i + 1)[0]});
}
}
boolean[] ans = new boolean[ask.length];
if(pos.size() == 0){
Arrays.fill(ans, true);
return ans;
}
for(int i = 0; i < ask.length; i++){
int idx = helper(pos, ask[i]);
if(idx != pos.size() && pos.get(idx)[0] < ask[i][1]){
ans[i] = false;
}else if(idx != 0 && pos.get(idx - 1)[1] > ask[i][0]){
ans[i] = false;
}else{
ans[i] = true;
}
}
return ans;
}
/**
* 使用二分查找 寻找到 pos.get(i)[1] 大于 one[0]
* @param pos
* @param one
* @return
*/
private int helper(List<int[]> pos, int[] one){
int left = 0;
int right = pos.size() - 1;
while(left <= right){
int mid = (left + right) >> 1;
if(pos.get(mid)[1] > one[0]){
right = mid - 1;
} else {
left = mid + 1;
}
}
return left;
}
public static void main(String[] args) {
int[][] intervals = {{1,2},{4,5},{8,10}};
int rooms = 1;
int[][] ask = {{2, 3}, {3, 4}};
MeetingRoomIII meetingRoomIII = new MeetingRoomIII();
boolean[] booleans = meetingRoomIII.meetingRoomIII(intervals, rooms, ask);
}
}
1897 · 会议室 3(区间判重和最大重叠区间问题)
最新推荐文章于 2023-06-08 07:24:12 发布