-
Notifications
You must be signed in to change notification settings - Fork 46
/
_855.java
88 lines (77 loc) · 2.77 KB
/
_855.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import java.util.*;
/**
* LeetCode 855 - Exam Room
* <p>
* O(log m) amortized runtime for both seat() and leave().
*/
public class _855 {
int N;
TreeSet<Integer> seated = new TreeSet<>();
PriorityQueue<List<Integer>> intervals = new PriorityQueue<>(Comparator.<List<Integer>>comparingInt(i -> -maxDistPerInterval(i)).thenComparingInt(i -> i.get(0)));
/**
* [x] has distance 1, seating at x
* [x, x + 1] has distance 1, seating at x
* [x, x + 1, x + 2] has distance 2, seating at x + 1
* [x, x + 1, x + 2, x + 3] has distance 2, seating at x + 1
* [x, x + 1, x + 2, x + 3, x + 4] has distance 3, seating at x + 2
* [x, x + 1, x + 2, x + 3, x + 4, x + 5] has distance 3, seating at x + 2
* ...
*/
private int maxDistPerInterval(List<Integer> i) {
return (i.get(1) - i.get(0)) / 2 + 1;
}
/**
* An interval [left, right] is valid if and only if
* <p>
* 1. 0 <= left <= right < N
* 2. For all i in [left, right], there is NO person currently sitting at the i-th seat.
*/
private boolean isValid(List<Integer> interval) {
if (interval.get(0) < 0 || interval.get(1) >= N || interval.get(0) > interval.get(1)) {
return false;
}
return seated.ceiling(interval.get(0)) > interval.get(1);
}
public _855(int N) {
this.N = N;
seated.add(-1);
seated.add(N);
}
public int seat() {
while (!intervals.isEmpty() && !isValid(intervals.peek())) {
intervals.poll();
}
int seat = -1, maxDistance = -1;
if (!intervals.isEmpty()) {
List<Integer> interval = intervals.poll();
int dist = maxDistPerInterval(interval);
if (dist > maxDistance) {
maxDistance = dist;
seat = (interval.get(0) + interval.get(1)) / 2;
}
}
// Seating at 0 or N - 1 is different from other cases. So deal with them separately.
if (!seated.contains(0) && seated.higher(0) - 0 > maxDistance) {
maxDistance = seated.higher(0) - 0;
seat = 0;
}
if (!seated.contains(N - 1) && N - 1 - seated.lower(N - 1) > maxDistance) {
maxDistance = N - 1 - seated.lower(N - 1);
seat = N - 1;
}
seated.add(seat);
intervals.add(Arrays.asList(seated.lower(seat) + 1, seat - 1));
intervals.add(Arrays.asList(seat + 1, seated.higher(seat) - 1));
return seat;
}
public void leave(int p) {
seated.remove(p);
intervals.add(Arrays.asList(seated.lower(p) + 1, seated.higher(p) - 1));
}
}
/**
* Your ExamRoom object will be instantiated and called as such:
* ExamRoom obj = new ExamRoom(N);
* int param_1 = obj.seat();
* obj.leave(p);
*/