Number of Airplanes in the Sky 思路:经典扫描线算法:把interval起飞和降落做为event,全部打散,按照时间排列,同时时间相等的,按照降落在前面,起飞在后面进行排序;最后再扫一遍,遇见start,count++,遇见end,count--,然后最后中间出现的最大值,就是题目所求。
/**
* Definition of Interval:
* public classs Interval {
* int start, end;
* Interval(int start, int end) {
* this.start = start;
* this.end = end;
* }
* }
*/
public class Solution {
/**
* @param airplanes: An interval array
* @return: Count of airplanes are in the sky.
*/
private class Node {
public int time;
public int flag;
public Node(int time, int flag) {
this.time = time;
this.flag = flag;
}
}
public int countOfAirplanes(List airplanes) {
int count = 0;
List list = new ArrayList();
for(Interval interval: airplanes) {
list.add(new Node(interval.start, 1));
list.add(new Node(interval.end, -1));
}
Collections.sort(list, (a, b) -> a.time != b.time ? a.time - b.time : a.flag - b.flag);
int maxplane = 0;
for(int i = 0; i < list.size(); i++) {
Node node = list.get(i);
if(node.flag == 1) {
count++;
} else {
count--;
}
maxplane = Math.max(maxplane, count);
}
return maxplane;
}
}
Meeting Rooms II 思路:题目跟上面飞机一模一样,代码都是一样的。
class Solution {
private class Node {
public int time;
public int flag;
public Node(int time, int flag) {
this.time = time;
this.flag = flag;
}
}
public int minMeetingRooms(int[][] intervals) {
if(intervals == null || intervals.length == 0 || intervals[0].length == 0) {
return 0;
}
List list = new ArrayList();
for(int i = 0; i < intervals.length; i++) {
list.add(new Node(intervals[i][0], 1));
list.add(new Node(intervals[i][1], -1));
}
Collections.sort(list, (a, b) -> (
a.time != b.time ? a.time - b.time : a.flag - b.flag));
int count = 0;
int maxcount = 0;
for(int i = 0; i < list.size(); i++) {
Node node = list.get(i);
if(node.flag == 1) {
count++;
} else {
count--;
}
maxcount = Math.max(maxcount, count);
}
return maxcount;
}
}
Time Intersection 思路:扫描线算法,注意的是,阈值发生变化的时候,收集数据,一定要在count = 2的时候收集。
/**
* Definition of Interval:
* public classs Interval {
* int start, end;
* Interval(int start, int end) {
* this.start = start;
* this.end = end;
* }
* }
*/
public class Solution {
/**
* @param seqA: the list of intervals
* @param seqB: the list of intervals
* @return: the time periods
*/
private class Node {
public int time;
public int flag;
public Node(int time, int flag) {
this.time = time;
this.flag = flag;
}
}
private class NodeComparator implements Comparator {
@Override
public int compare(Node a, Node b) {
if(a.time != b.time) {
return a.time - b.time;
} else {
return a.flag - b.flag; // define flag 1 is online, 0 is offline;
}
}
}
public List timeIntersection(List seqA, List seqB) {
List result = new ArrayList();
if(seqA == null || seqA.size() == 0 || seqB == null || seqB.size() == 0) {
return result;
}
int n = seqA.size();
int m = seqB.size();
Node[] nodes = new Node[n * 2 + m * 2];
int index = 0;
for(int i = 0; i < n; i++) {
nodes[index++] = new Node(seqA.get(i).start, 1);
nodes[index++] = new Node(seqA.get(i).end, 0);
}
for(int i = 0; i < m; i++) {
nodes[index++] = new Node(seqB.get(i).start, 1);
nodes[index++] = new Node(seqB.get(i).end, 0);
}
Arrays.sort(nodes, new NodeComparator());
int count = 0;
int start = 0;
int end = 0;
for(int i = 0; i < nodes.length; i++) {
if(nodes[i].flag == 1) {
count++;
if(count == 2) {
start = nodes[i].time;
}
}
if(nodes[i].flag == 0) {
if(count == 2) { //每次都是阈值发生变化的时候,收集interval;
end = nodes[i].time;
result.add(new Interval(start, end));
start = 0;
end = 0;
}
count--;
}
}
return result;
}
}
思路2:这题因为数据是sorted,因为A和B都是sorted,那么跟merge array一样,可以用打擂台的方式,每次踢走一个。
如果Max(startA, startB) < Min(endA, endB)则加入相交的interval 然后看A, B end 谁大,谁留下,另外一个踢走;O(N+M)
// 因为数据是sorted,那么就按照overlap来扫描,也就是start取最大值,end取最小值,
// 如果start< end,表明有overlap,否则不会有overlap,同时end较小的扔掉,较大的留下;
/**
* Definition of Interval:
* public classs Interval {
* int start, end;
* Interval(int start, int end) {
* this.start = start;
* this.end = end;
* }
* }
*/
public class Solution {
/**
* @param seqA: the list of intervals
* @param seqB: the list of intervals
* @return: the time periods
*/
public List timeIntersection(List seqA, List seqB) {
List result = new ArrayList();
if(seqA == null || seqA.size() == 0 || seqB == null || seqB.size() == 0) {
return result;
}
int aIndex = 0;
int bIndex = 0;
// 因为数据是sorted,那么就按照overlap来扫描,也就是start取最大值,end取最小值,
// 如果start< end,表明有overlap,否则不会有overlap,同时end较小的扔掉,较大的留下;
while(aIndex < seqA.size() && bIndex < seqB.size()) {
int start = Math.max(seqA.get(aIndex).start, seqB.get(bIndex).start);
int end = Math.min(seqA.get(aIndex).end, seqB.get(bIndex).end);
if(start < end) {
result.add(new Interval(start, end));
}
if(seqA.get(aIndex).end < seqB.get(bIndex).end) {
aIndex++;
} else {
bIndex++;
}
}
return result;
}
}
Meeting Scheduler: 跟上面一样,两个array按照start,sort之后,打擂台的方式,判断如果相交,那么end - start >= duration那么就收集[start, start + duration] 返回,否则,end大的留下,小的扔掉;T( mlogm + nlogn);
class Solution {
public List minAvailableDuration(int[][] slots1, int[][] slots2, int duration) {
List list = new ArrayList();
Arrays.sort(slots1, (a, b) -> (a[0] - b[0]));
Arrays.sort(slots2, (a, b) -> (a[0] - b[0]));
int a = 0; int b = 0;
while(a < slots1.length && b < slots2.length) {
int start = Math.max(slots1[a][0], slots2[b][0]);
int end = Math.min(slots1[a][1], slots2[b][1]);
if(start < end && end - start >= duration) {
list.add(start);
list.add(start + duration);
return list;
} else {
if(slots1[a][1] > slots2[b][1]) {
b++;
} else {
a++;
}
}
}
return list;
}
}
Skyline problem: 思路:扫描线算法;起飞的时候才加入一堆高度进行排序判断最高height,下降的时候,要remove 当前的高度,由于下降的点刚开始存的时候就是负数,所以remove的时候就是remove -负数。不参加评选了。还有注意点就是pq刚开始有可能是空的时候,curheight是0. 否则会报NPE;
class Solution {
private class Node {
public int x;
public int height;
public Node(int x, int height) {
this.x = x;
this.height = height;
}
}
public List> getSkyline(int[][] buildings) {
List> lists = new ArrayList>();
if(buildings == null || buildings.length == 0 || buildings[0].length == 0) {
return lists;
}
PriorityQueue pq = new PriorityQueue((a, b) -> (b - a));
List nodes = new ArrayList();
for(int i = 0; i < buildings.length; i++) {
nodes.add(new Node(buildings[i][0], buildings[i][2]));
nodes.add(new Node(buildings[i][1], -buildings[i][2]));
}
Collections.sort(nodes, (a, b) -> (a.x != b.x ? a.x - b.x : b.height - a.height));
int preheight = 0;
int curheight = 0;
for(int i = 0; i < nodes.size(); i++) {
Node node = nodes.get(i);
if(node.height > 0) {
// 起飞的时候,加入pq进行排序;
pq.offer(node.height);
} else {
// 因为下降的点,height是负数,所以这里要remove -height;
pq.remove(-node.height);
}
// 注意这里要判断pq是否为空,为空就是0,不为空才是peek;
curheight = pq.isEmpty() ? 0 : pq.peek();
if(curheight != preheight) {
List list = new ArrayList();
list.add(node.x);
list.add(curheight);
lists.add(list);
preheight = curheight;
}
}
return lists;
}
}