@@ -727,80 +727,109 @@ int search(vector<int> &nums, int target)
727
727
### [Exam Room](https://leetcode.com/problems/exam-room/)
728
728
```c++
729
729
// O(N) seat and O(logN) leave
730
- int numOfStudents ;
730
+ int totalSeats ;
731
731
set<int> locations;
732
- ExamRoom(int N) : numOfStudents(N) { }
732
+
733
+ ExamRoom(int N): totalSeats(N) { }
733
734
void leave(int p) { locations.erase(p); }
734
- int seat()
735
- {
736
- int dist = 0, studentToSit = 0;
737
- if (!locations.empty())
738
- {
739
- auto beg = locations.begin();
740
- if (*beg != 0) dist = *beg;
741
- for (auto it = next(beg); it != locations.end(); ++it)
742
- {
743
- int curDist = (*it - *beg)/2;
744
- if (curDist > dist) dist = curDist, studentToSit = *beg + dist;
745
- beg = it;
735
+ int seat() {
736
+ int posToUse = 0;
737
+ if (!locations.empty()) {
738
+ int optimalDistance = *locations.begin();
739
+ for (auto i = locations.begin(), j = next(locations.begin()); j != locations.end(); ++i, ++j) {
740
+ int distance = (*j - *i) / 2;
741
+ if (distance > optimalDistance)
742
+ optimalDistance = distance, posToUse = *i + distance;
746
743
}
747
- beg = prev(locations.end());
748
- if (numOfStudents - *beg - 1 > dist) studentToSit = numOfStudents-1;
744
+ int lastDistance = totalSeats - *prev(locations.end()) - 1;
745
+ if (lastDistance > optimalDistance)
746
+ optimalDistance = lastDistance, posToUse = totalSeats - 1;
749
747
}
750
- locations.insert(studentToSit );
751
- return studentToSit ;
748
+ locations.insert(posToUse );
749
+ return posToUse ;
752
750
}
753
751
754
752
// O(logN) seat and O(logN) leave
755
- int n;
756
- set<int> cur; // stores point at which student is placed
757
- set<pair<int, int>, greater<pair<int, int>>> cand; // stores [min_dist, -point] pair for possible future candidates. Pick one with highest distance and lowest index.
758
- ExamRoom(int N) : n(N) { }
759
- void addCandidate(int a, int b)
760
- {
761
- int nextInd = (a + b)/2;
762
- if (nextInd != a) cand.emplace(min(abs(b - nextInd), abs(a - nextInd)), -nextInd);
753
+ int totalSeats;
754
+ set<int> locations;
755
+ // This set stores the future possibilities, idea is when we place a student there are
756
+ // two new possibilities, left or right that we create. pair stores [min_dist, -point]
757
+ // Pick one with highest distance and lowest index.
758
+ set<pair<int, int>, greater<pair<int, int>>> possibilities;
759
+
760
+ // Given two locations first & second, add candidate in the middle.
761
+ void addCandidate(int first, int second) {
762
+ int nextIndex = (first + second) / 2;
763
+ if (nextIndex != first)
764
+ possibilities.insert({min(abs(first - nextIndex), abs(second - nextIndex)), -nextIndex});
763
765
}
764
- void deleteCandidate(int a, int b)
766
+
767
+ // Given two locations first & second, add candidate in the middle.
768
+ void deleteCandidate(int first, int second)
765
769
{
766
- int nextInd = (a + b)/2;
767
- if (nextInd != a) cand.erase({min(abs(b - nextInd), abs(a - nextInd)), -nextInd});
770
+ int nextIndex = (first + second) / 2;
771
+ if (nextIndex != first)
772
+ possibilities.erase({min(abs(first - nextIndex), abs(second - nextIndex)), -nextIndex});
768
773
}
769
774
770
- int seat()
771
- {
772
- if (cur.empty()) { cur.insert(0); cand.emplace(n-1, -(n-1)); return 0; }
773
- // Place student on highest distance i.e. begin of cand, then placing new means breaking candidate area into two so adding them
774
- auto [len, ind] = *cand.begin();
775
- ind = -ind;
776
- cand.erase(cand.begin());
777
- auto nxt = cur.upper_bound(ind);
778
- if (nxt != cur.end()) addCandidate(ind, *nxt);
779
- auto prev = cur.upper_bound(ind);
780
- if (prev != cur.begin()) { prev--; addCandidate(*prev, ind); }
781
- cur.insert(ind);
782
- return ind;
775
+ ExamRoom(int N): totalSeats(N) { }
776
+ int seat() {
777
+ if (locations.empty()) {
778
+ locations.insert(0);
779
+ possibilities.insert({totalSeats-1, -(totalSeats-1)});
780
+ return 0;
781
+ }
782
+
783
+ // Take the best possibility, and place the student there.
784
+ // After taking the possbility, it cannot be used in future.
785
+ auto [minDistance, point] = *possibilities.begin();
786
+ point *= -1;
787
+ possibilities.erase(possibilities.begin());
788
+
789
+ // Taken choice, divides the vacant seats in two parts add them as possibility.
790
+ auto upperBoundLocation = locations.upper_bound(point);
791
+ if (upperBoundLocation != locations.end()) addCandidate(point, *upperBoundLocation);
792
+ if (upperBoundLocation != locations.begin()) addCandidate(point, *prev(upperBoundLocation));
793
+
794
+ locations.insert(point);
795
+ return point;
783
796
}
784
- void leave(int p)
785
- {
786
- cur.erase(p);
787
- if (cur.empty()) { cand.clear(); return; }
788
- int nextInd = -1, prevInd = -1;
789
- auto nxt = cur.upper_bound(p);
790
- if (nxt != cur.end()) { nextInd = *nxt; deleteCandidate(p, *nxt); }
791
- auto prev = cur.upper_bound(p);
792
- if (prev != cur.begin()) { prev--, prevInd = *prev; deleteCandidate(*prev, p); }
793
- if (cur.size() == 1)
797
+
798
+ void leave(int p) {
799
+ locations.erase(p);
800
+ if (locations.empty()) {
801
+ possibilities.clear();
802
+ return;
803
+ }
804
+
805
+ // If a student leaves, it removes old small possibilities that were in left and right side.
806
+ // Instead a new bigger possibility comes in that place.
807
+ int nextIndex = -1, prevIndex = -1;
808
+ auto upperBoundLocation = locations.upper_bound(p);
809
+ if (upperBoundLocation != locations.end()) {
810
+ nextIndex = *upperBoundLocation;
811
+ deleteCandidate(nextIndex, p);
812
+ }
813
+ if (upperBoundLocation != locations.begin()) {
814
+ prevIndex = *prev(upperBoundLocation);
815
+ deleteCandidate(prevIndex, p);
816
+ }
817
+
818
+ // If initially there were two students one left now new set of possibilities exist at left & right
819
+ // side of that remaining student.
820
+ if (locations.size() == 1)
794
821
{
795
- cand .clear();
796
- int ind = *cur .begin();
797
- if (ind != 0) cand.emplace( ind, 0);
798
- if (ind != n -1) cand.emplace(n-1- ind, -(n -1));
822
+ possibilities .clear();
823
+ int ind = *locations .begin();
824
+ if (ind != 0) possibilities.insert({ ind, 0} );
825
+ if (ind != totalSeats -1) possibilities.insert({totalSeats - 1 - ind, -(totalSeats -1)} );
799
826
return;
800
827
}
801
- if (p == 0) cand.emplace(*cur.begin(), 0);
802
- else if (p == n-1) cand.emplace(n-1-*cur.rbegin(), -(n-1));
803
- else if (nextInd >= 0 && prevInd >= 0) addCandidate(prevInd, nextInd);
828
+
829
+ // Need three cases 1) extreme left, 2) extreme right, and 3) middle.
830
+ if (p == 0) possibilities.insert({*locations.begin(), 0});
831
+ else if (p == totalSeats-1) possibilities.insert({totalSeats - 1 - *locations.rbegin(), -(totalSeats-1)});
832
+ else if (nextIndex >= 0 && prevIndex >= 0) addCandidate(prevIndex, nextIndex);
804
833
}
805
834
```
806
835
0 commit comments