题目地址:
https://www.lintcode.com/problem/parking-problem/description
给定一系列停车场出入记录,问最多的时候停车场停了多少车。时间点都是整数,如果遇到出场时间早于等于入场时间则视为无效记录;如果同一时刻同时有某辆车的进记录和某辆车的出记录,则先出后入。
法1:最小堆。参考https://blog.csdn.net/qq_46105170/article/details/108675668。开个最小堆,存出入时间,并且出场时间早的更优先。基本思路是,每次来一个车的时候,先看一下之前停的车哪辆可以把位子让出来,如果有(有意味着出场时间早于等于新来的车的入场时间),则将其出堆,将新的车入堆;如果没有车子能让出位置,那只能将新车直接入堆了(意味着要新占用一个车位)。最后返回堆的size。代码如下:
import java.util.Arrays;
import java.util.PriorityQueue;
public class Solution {
/**
* @param a: the Parking Record
* @return: The max number of cars
*/
public int getMax(int[][] a) {
// Write your code here
PriorityQueue<int[]> minHeap = new PriorityQueue<>((t1, t2) -> Integer.compare(t1[1], t2[1]));
Arrays.sort(a, (t1, t2) -> Integer.compare(t1[0], t2[0]));
for (int[] t : a) {
// 无效记录略过
if (t[0] >= t[1]) {
continue;
}
if (!minHeap.isEmpty() && minHeap.peek()[1] <= t[0]) {
minHeap.poll();
}
minHeap.offer(t);
}
return minHeap.size();
}
}
时间复杂度 O ( n log n ) O(n\log n) O(nlogn),空间 O ( n ) O(n) O(n)。
法2:TreeMap扫描线。参考https://blog.csdn.net/qq_46105170/article/details/108675668。开一个TreeMap,key存时间点,value存当前净入场车数。对于每个时间点,如果有入场,则记 1 1 1,否则记 − 1 -1 −1。最后按时间顺序遍历TreeMap,累计某个时间点的车辆数,同时更新答案。代码如下:
import java.util.Map;
import java.util.TreeMap;
public class Solution {
/**
* @param a: the Parking Record
* @return: The max number of cars
*/
public int getMax(int[][] a) {
// Write your code here
Map<Integer, Integer> map = new TreeMap<>();
for (int[] t : a) {
if (t[0] >= t[1]) {
continue;
}
map.put(t[0], map.getOrDefault(t[0], 0) + 1);
map.put(t[1], map.getOrDefault(t[1], 0) - 1);
}
int res = 0, count = 0;
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
count += entry.getValue();
res = Math.max(res, count);
}
return res;
}
}
时空复杂度一样。