Skip to content

Commit bb3f395

Browse files
Update searching.md
1 parent 0a0b236 commit bb3f395

File tree

1 file changed

+88
-59
lines changed

1 file changed

+88
-59
lines changed

searching.md

Lines changed: 88 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -727,80 +727,109 @@ int search(vector<int> &nums, int target)
727727
### [Exam Room](https://leetcode.com/problems/exam-room/)
728728
```c++
729729
// O(N) seat and O(logN) leave
730-
int numOfStudents;
730+
int totalSeats;
731731
set<int> locations;
732-
ExamRoom(int N) : numOfStudents(N) { }
732+
733+
ExamRoom(int N): totalSeats(N) { }
733734
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;
746743
}
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;
749747
}
750-
locations.insert(studentToSit);
751-
return studentToSit;
748+
locations.insert(posToUse);
749+
return posToUse;
752750
}
753751
754752
// 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});
763765
}
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)
765769
{
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});
768773
}
769774
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;
783796
}
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)
794821
{
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)});
799826
return;
800827
}
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);
804833
}
805834
```
806835

0 commit comments

Comments
 (0)