|
| 1 | +package LeetCodeJava.Heap; |
| 2 | + |
| 3 | +// https://leetcode.com/problems/exam-room/description/ |
| 4 | +/** |
| 5 | + * 855. Exam Room |
| 6 | + * Medium |
| 7 | + * Topics |
| 8 | + * Companies |
| 9 | + * There is an exam room with n seats in a single row labeled from 0 to n - 1. |
| 10 | + * <p> |
| 11 | + * When a student enters the room, they must sit in the seat that maximizes the distance to the closest person. If there are multiple such seats, they sit in the seat with the lowest number. If no one is in the room, then the student sits at seat number 0. |
| 12 | + * <p> |
| 13 | + * Design a class that simulates the mentioned exam room. |
| 14 | + * <p> |
| 15 | + * Implement the ExamRoom class: |
| 16 | + * <p> |
| 17 | + * ExamRoom(int n) Initializes the object of the exam room with the number of the seats n. |
| 18 | + * int seat() Returns the label of the seat at which the next student will set. |
| 19 | + * void leave(int p) Indicates that the student sitting at seat p will leave the room. It is guaranteed that there will be a student sitting at seat p. |
| 20 | + * <p> |
| 21 | + * <p> |
| 22 | + * Example 1: |
| 23 | + * <p> |
| 24 | + * Input |
| 25 | + * ["ExamRoom", "seat", "seat", "seat", "seat", "leave", "seat"] |
| 26 | + * [[10], [], [], [], [], [4], []] |
| 27 | + * Output |
| 28 | + * [null, 0, 9, 4, 2, null, 5] |
| 29 | + * <p> |
| 30 | + * Explanation |
| 31 | + * ExamRoom examRoom = new ExamRoom(10); |
| 32 | + * examRoom.seat(); // return 0, no one is in the room, then the student sits at seat number 0. |
| 33 | + * examRoom.seat(); // return 9, the student sits at the last seat number 9. |
| 34 | + * examRoom.seat(); // return 4, the student sits at the last seat number 4. |
| 35 | + * examRoom.seat(); // return 2, the student sits at the last seat number 2. |
| 36 | + * examRoom.leave(4); |
| 37 | + * examRoom.seat(); // return 5, the student sits at the last seat number 5. |
| 38 | + * <p> |
| 39 | + * <p> |
| 40 | + * <p> |
| 41 | + * Constraints: |
| 42 | + * <p> |
| 43 | + * 1 <= n <= 109 |
| 44 | + * It is guaranteed that there is a student sitting at seat p. |
| 45 | + * At most 104 calls will be made to seat and leave. |
| 46 | + */ |
| 47 | + |
| 48 | +import java.util.TreeSet; |
| 49 | + |
| 50 | +/** |
| 51 | + * Your ExamRoom object will be instantiated and called as such: |
| 52 | + * ExamRoom obj = new ExamRoom(n); |
| 53 | + * int param_1 = obj.seat(); |
| 54 | + * obj.leave(p); |
| 55 | + */ |
| 56 | +public class ExamRoom { |
| 57 | + |
| 58 | + // V0 |
| 59 | +// class ExamRoom { |
| 60 | +// |
| 61 | +// public ExamRoom(int n) { |
| 62 | +// |
| 63 | +// } |
| 64 | +// |
| 65 | +// public int seat() { |
| 66 | +// |
| 67 | +// } |
| 68 | +// |
| 69 | +// public void leave(int p) { |
| 70 | +// |
| 71 | +// } |
| 72 | +// } |
| 73 | + |
| 74 | + // V1 |
| 75 | + |
| 76 | + // V2 |
| 77 | + // (offered by gpt) |
| 78 | + public class ExamRoom_2 { |
| 79 | + private TreeSet<Integer> seats; |
| 80 | + private int n; |
| 81 | + |
| 82 | + public ExamRoom_2(int n) { |
| 83 | + this.n = n; |
| 84 | + this.seats = new TreeSet<>(); |
| 85 | + } |
| 86 | + |
| 87 | + public int seat() { |
| 88 | + int seat = 0; |
| 89 | + |
| 90 | + if (seats.size() > 0) { |
| 91 | + // Initialize the max distance and seat to sit at |
| 92 | + int maxDist = seats.first(); |
| 93 | + seat = 0; // sitting at the first seat |
| 94 | + |
| 95 | + Integer prev = null; |
| 96 | + for (Integer s : seats) { |
| 97 | + if (prev != null) { |
| 98 | + int dist = (s - prev) / 2; |
| 99 | + if (dist > maxDist) { |
| 100 | + maxDist = dist; |
| 101 | + seat = prev + dist; |
| 102 | + } |
| 103 | + } |
| 104 | + prev = s; |
| 105 | + } |
| 106 | + |
| 107 | + // Consider sitting at the last seat |
| 108 | + if (n - 1 - seats.last() > maxDist) { |
| 109 | + seat = n - 1; |
| 110 | + } |
| 111 | + } |
| 112 | + |
| 113 | + // Add the seat to the occupied set |
| 114 | + seats.add(seat); |
| 115 | + return seat; |
| 116 | + } |
| 117 | + |
| 118 | + public void leave(int p) { |
| 119 | + seats.remove(p); |
| 120 | + } |
| 121 | + |
| 122 | + } |
| 123 | + |
| 124 | + // V3 |
| 125 | + // https://leetcode.com/problems/exam-room/solutions/1331530/easy-to-understand-java-solution-with-explanation-treeset/0 |
| 126 | + class ExamRoom_3 { |
| 127 | + |
| 128 | + int capacity; // this is just to keep track of the max allowed size |
| 129 | + TreeSet<Integer> seats; |
| 130 | + /* why treeset, because seats will be sorted automatically |
| 131 | + and get first()/last() element in log(n) time. |
| 132 | + */ |
| 133 | + |
| 134 | + public ExamRoom_3(int n) { |
| 135 | + this.capacity = n; |
| 136 | + this.seats = new TreeSet<>(); |
| 137 | + } |
| 138 | + |
| 139 | + public int seat() { |
| 140 | + int seatNumber = 0; |
| 141 | + /* |
| 142 | + Return 0 for first attempt ( as mentioned in question) |
| 143 | + Otherwise, we need to calculate the max distance by checking the whole treeset : O(n) time. |
| 144 | + Note that "distance" variable is initialized to first appearing seat, |
| 145 | + why because the distance calculation is based on current seat and the seat before that. |
| 146 | + Find the maximum distance and update the seat number accordingly. |
| 147 | + distance calculation -> (current seat - previous seat )/ 2 |
| 148 | + Update the max distance at each step. |
| 149 | + New seat number will be -> previous seat number + max distance |
| 150 | +
|
| 151 | + Now, before returning the end result, check for one more edge case: |
| 152 | + That is, if the max distance calculated is less than -> capacity-1-seats.last() |
| 153 | +
|
| 154 | + Why because -> if last seat number in treeset is far from last position, |
| 155 | + then the largest distance possible is the last position. |
| 156 | +
|
| 157 | + */ |
| 158 | + if (seats.size() > 0) { |
| 159 | + Integer prev = null; |
| 160 | + int distance = seats.first(); |
| 161 | + for (Integer seat : seats) { |
| 162 | + if (prev != null) { |
| 163 | + int d = (seat - prev) / 2; |
| 164 | + if (distance < d) { |
| 165 | + distance = d; |
| 166 | + seatNumber = prev + distance; |
| 167 | + } |
| 168 | + } |
| 169 | + prev = seat; |
| 170 | + } |
| 171 | + |
| 172 | + if (distance < capacity - 1 - seats.last()) { |
| 173 | + seatNumber = capacity - 1; |
| 174 | + } |
| 175 | + } |
| 176 | + seats.add(seatNumber); |
| 177 | + return seatNumber; |
| 178 | + } |
| 179 | + |
| 180 | + public void leave(int p) { |
| 181 | + seats.remove(p); |
| 182 | + /* simply remove the seat number from treeset |
| 183 | + and treeset will be automatically adjust its order in log(n) time. |
| 184 | + */ |
| 185 | + } |
| 186 | + } |
| 187 | + |
| 188 | + // V4 |
| 189 | + // https://leetcode.com/problems/exam-room/solutions/2824662/java-simple-one-treeset-solution-with-o-n-seat-and-o-logn-leave/ |
| 190 | + class ExamRoom_4 { |
| 191 | + int N; |
| 192 | + TreeSet<Integer> seats; |
| 193 | + public ExamRoom_4(int n) { |
| 194 | + seats = new TreeSet<>(); // ordered set to keep track of students |
| 195 | + this.N = n; |
| 196 | + } |
| 197 | + |
| 198 | + public int seat() { |
| 199 | + int student = 0; |
| 200 | + |
| 201 | + if (seats.size() > 0) { // if at least one student, otherwise seat at 0 |
| 202 | + int dist = seats.first(); // the student at lowest seat |
| 203 | + Integer prev = null; |
| 204 | + for (Integer seat: seats) { |
| 205 | + if (prev != null) { |
| 206 | + int d = (seat - prev)/2; // every time we see a new student we can seat them between 2 other students |
| 207 | + if (d > dist) { // select the max range |
| 208 | + dist = d; |
| 209 | + student = prev + d; |
| 210 | + } |
| 211 | + } |
| 212 | + prev = seat; |
| 213 | + } |
| 214 | + if (N - 1 - seats.last() > dist) { |
| 215 | + student = N-1; |
| 216 | + } |
| 217 | + } |
| 218 | + seats.add(student); |
| 219 | + return student; |
| 220 | + } |
| 221 | + |
| 222 | + public void leave(int p) { |
| 223 | + seats.remove(p); |
| 224 | + } |
| 225 | + } |
| 226 | + |
| 227 | + // V5 |
| 228 | + // https://leetcode.com/problems/exam-room/solutions/2085063/java-o-logn-seat-leave-treeset-solution/ |
| 229 | + class ExamRoom_5 { |
| 230 | + |
| 231 | + private final int max; |
| 232 | + private final TreeSet<Interval> available; |
| 233 | + private final TreeSet<Integer> taken; |
| 234 | + |
| 235 | + public ExamRoom_5(int n) { |
| 236 | + this.max = n - 1; |
| 237 | + this.available = new TreeSet<>((a, b) -> { |
| 238 | + int distA = getMinDistance(a); |
| 239 | + int distB = getMinDistance(b); |
| 240 | + return distA == distB ? a.s - b.s : distB - distA; |
| 241 | + }); |
| 242 | + this.available.add(new Interval(0, max)); |
| 243 | + this.taken = new TreeSet<>(); |
| 244 | + } |
| 245 | + |
| 246 | + public int seat() { |
| 247 | + Interval inter = available.pollFirst(); |
| 248 | + int idx = getInsertPosition(inter); |
| 249 | + taken.add(idx); |
| 250 | + if ((idx - 1) - inter.s >= 0) |
| 251 | + available.add(new Interval(inter.s, idx - 1)); |
| 252 | + if (inter.e - (idx + 1) >= 0) |
| 253 | + available.add(new Interval(idx + 1, inter.e)); |
| 254 | + return idx; |
| 255 | + } |
| 256 | + |
| 257 | + public void leave(int p) { |
| 258 | + taken.remove(p); |
| 259 | + Integer lo = taken.lower(p); |
| 260 | + if (lo == null) |
| 261 | + lo = -1; |
| 262 | + Integer hi = taken.higher(p); |
| 263 | + if (hi == null) |
| 264 | + hi = max + 1; |
| 265 | + available.remove(new Interval(lo + 1, p - 1)); |
| 266 | + available.remove(new Interval(p + 1, hi - 1)); |
| 267 | + available.add(new Interval(lo + 1, hi - 1)); |
| 268 | + } |
| 269 | + |
| 270 | + private int getInsertPosition(Interval inter) { |
| 271 | + if (inter.s == 0) |
| 272 | + return 0; |
| 273 | + else if (inter.e == max) |
| 274 | + return max; |
| 275 | + else |
| 276 | + return inter.s + (inter.e - inter.s) / 2; |
| 277 | + } |
| 278 | + |
| 279 | + private int getMinDistance(Interval in) { |
| 280 | + return in.s == 0 || in.e == max ? in.e - in.s : (in.e - in.s) / 2; |
| 281 | + } |
| 282 | + |
| 283 | + private final class Interval { |
| 284 | + private final int s; |
| 285 | + private final int e; |
| 286 | + |
| 287 | + Interval(int s, int e) { |
| 288 | + this.s = s; |
| 289 | + this.e = e; |
| 290 | + } |
| 291 | + |
| 292 | + @Override |
| 293 | + public String toString() { |
| 294 | + return "[" + s + "," + e + "]"; |
| 295 | + } |
| 296 | + } |
| 297 | + } |
| 298 | + |
| 299 | +} |
0 commit comments