Leetcode 855. Exam Room 시험장 착석: 두 가지 해법 제공
Leetcode 855. Exam Room 시험장 착석: 두 가지 해법 제공
855. Exam Room 시험장 착석(두 가지 해법)
제목 설명
In an exam room, there are N seats in a single row, numbered 0, 1, 2, …, N-1.
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. (Also, if no one is in the room, then the student sits at seat number 0.)
Return a class ExamRoom(int N) that exposes two functions: ExamRoom.seat() returning an int representing what seat the student sat in, and ExamRoom.leave(int p) representing that the student in seat number p now leaves the room. It is guaranteed that any calls to ExamRoom.leave§ have a student sitting in seat p.
Note:
1 <= N <= 10^9 ExamRoom.seat() and ExamRoom.leave() will be called at most 10^4 times across all test cases. Calls to ExamRoom.leave§ are guaranteed to have a student currently sitting in seat number p.
예:
Example 1:
Input: ["ExamRoom","seat","seat","seat","seat","leave","seat"], [[10],[],[],[],[],[4],[]]
Output: [null,0,9,4,2,null,5]
Explanation:
ExamRoom(10) -> null
seat() -> 0, no one is in the room, then the student sits at seat number 0.
seat() -> 9, the student sits at the last seat number 9.
seat() -> 4, the student sits at the last seat number 4.
seat() -> 2, the student sits at the last seat number 2.
leave(4) -> null
seat() -> 5, the student sits at the last seat number 5.
해답
첫 번째 방법은 하나의vector로 좌석 번호를 저장하고 매번 좌석에 앉을 때마다 그룹을 옮겨다니며 가장 큰 좌석 간격을 찾은 다음에 이 간격의 중간 위치에 앉는다.
좌석을 떠날 때 바이어에서 이 좌석 번호를 삭제하면 됩니다.이 알고리즘의 복잡도는 선형이다.
코드 1
class ExamRoom {
int num = 0;
vector<int > row;
public:
ExamRoom(int N) {
num = N;
}
int seat() {
if (row.size() == 0) {
row.push_back(0);
return 0;
}
int d = max(row[0], num - 1 - row[row.size() - 1]);
for (int i = 1;i < row.size(); i ++) {
d = max(d, (row[i] - row[i - 1]) / 2);
}
if (d == row[0]) {
row.insert(row.begin(), 0);
return 0;
}
else {
for (int i = 1; i < row.size(); i++) {
if ((row[i] - row[i - 1]) / 2 == d) {
row.insert(row.begin() + i, (row[i] + row[i - 1]) / 2);
return row[i];
}
}
}
row.push_back(num - 1);
return num - 1;
}
void leave(int p) {
for (int i = 0; i < row.size(); i++) {
if (row[i] == p)
row.erase(row.begin() + i);
}
}
};
해답2
두 번째 아이디어 알고리즘의 복잡도는 O(l o g n) O(logn) O(logn)이다. 전역에서 maintain의 set 수조에서 좌석 간격에 따라 큰 것부터 작은 것까지 배열하고 매번 자리에 앉을 때마다 이 set 데이터의 첫 번째 위치의 간격을 빼고 이 간격을 둘로 나누어 이 set 데이터에 삽입한다.
자리를 떠날 때 set 수조에서 자리를 뜨는 사람이 관련된 두 개의 간격을 찾아 이 두 개의 간격을 합친 후에 set에 삽입하면 자리를 뜨는 것이 완성된다.
코드 2
struct IntV
{
static int N;
int l, r;
IntV(int l, int r) : l(l), r(r) {};
int getDistance() const {
if (l == 0) return r;
if (r == N - 1) return N - 1 - l;
if (r < l) return -1;
else return (r - l) / 2;
}
int getInsertPoint() const {
if (l == 0) return 0;
if (r == N - 1) return N - 1;
else return (l + r) / 2;
}
int operator < (const IntV& a) const {
int d1 = getDistance();
int d2 = a.getDistance();
if(d1 != d2) return d1 > d2;
return l < a.l;
}
};
int IntV :: N = 0;
class ExamRoom{
public:
set<IntV> interval;
map<int, int> r2l, l2r;
ExamRoom(int N) {
IntV::N = N;
interval.clear(); l2r.clear(); r2l.clear();
interval.insert(IntV(0, N - 1));
l2r[0] = N - 1;
r2l[N -1] = 0;
}
int seat() {
auto cur = *(interval.begin());
interval.erase(interval.begin());
int pos = cur.getInsertPoint();
cout << pos;
interval.insert(IntV(cur.l, pos - 1));
interval.insert(IntV(pos + 1, cur.r));
l2r[cur.l] = pos - 1;
r2l[pos - 1] = cur.l;
l2r[pos + 1] = cur.r;
r2l[cur.r] = pos + 1;
return pos;
}
void leave(int p) {
auto r = l2r[p + 1];
auto l = r2l[p - 1];
interval.erase(IntV(l, p - 1));
interval.erase(IntV(p + 1, r));
interval.insert(IntV(l, r));
l2r[l] = r;
r2l[r] = l;
r2l.erase(p - 1);
l2r.erase(p + 1);
}
};
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
0부터 시작하는 LeetCode Day8 「1302. Deepest Leaves Sum」해외에서는 엔지니어의 면접에 있어서 코딩 테스트라고 하는 것이 행해지는 것 같고, 많은 경우, 특정의 함수나 클래스를 주제에 따라 실장한다고 하는 것이 메인이다. 빠른 이야기가 본고장에서도 행해지고 있는 것 같은 코...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.