[LeetCode] 855. Exam Room 考試房間



In an exam room, there are N seats in a single row, numbered 0, 1, 2, ..., N-1.html

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.)git

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(p) have a student sitting in seat p.github

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.

​​​​​​​

Note:函數

  1. 1 <= N <= 10^9
  2. ExamRoom.seat() and ExamRoom.leave() will be called at most 10^4 times across all test cases.
  3. Calls to ExamRoom.leave(p) are guaranteed to have a student currently sitting in seat number p.



這道題是以前那道 Maximize Distance to Closest Person 的拓展,說是有個考場,每一個考生入座的時候都要儘量的跟左右兩邊的人距離保持最大,當最大距離相同的時候,考生坐在座位編號較小的那個位置。對於牆的處理跟以前那道是同樣的,能靠牆就儘可能靠牆,這樣確定離別人最遠。其實在以前那道題 Maximize Distance to Closest Person 最後的討論部分博主就預言了這道題,當時博主尚未看這道題,果真是要咱們返回座位的具體位置。優化

博主最早想的方法是用一個大小爲N的數組來表示全部的座位,初始化爲0,表示沒有一我的,如有人入座了,則將該位置變爲1,離開則變爲0,那麼對於 leave() 函數就十分簡單了,直接將對應位置改成0便可。重點就是 seat() 函數了,這個能夠借鑑以前那道 Maximize Distance to Closest Person 的思路,採用雙指針來作,主要就是找連續的0進行處理,仍是要分 start 是否爲0的狀況,由於空位從牆的位置開始,跟空位在兩人之間的處理狀況是不一樣的,若空位從牆開始,確定是坐牆邊,而如果在兩人之間,則須要坐在最中間,還要記得更新 start 爲下一個空座位。最後在處理末尾空位連到牆的時候,跟以前稍有些不一樣,由於題目要求當最大距離相同的時候,須要選擇座位號小的位置,而當此時 start 爲0的時候,說明全部的位置都是空的,那麼咱們不須要再更新 idx 了,就用其初始值0,表示就坐在第一個位置,是符合題意的。最後別忘了將 idx 位置賦值爲1,表示有人坐了。指針

看到這裏,你必定覺得大功告成了吧,but,OJ老是不斷給人驚喜,Time Limit Exceeded,貌似不讓咱們這麼輕易過關啊。那麼只能進行優化了,首先分析上面的思路哪塊比較耗時,其實就是遍歷,當有大量的空座位的時候,中間的0還得一個個遍歷,不是很高效,那麼比較直接的改進方法就是去掉那些0,咱們只保存有人坐的位置,即全部1的位置。這樣省去了遍歷0的時間,大大提升了效率,此時咱們就可使用 TreeSet 來保存1的位置,其他部分並不怎麼須要改變,在肯定了座位 idx 時,將其加入 TreeSet 中。在 leave() 中,直接移除離開人的座位位置便可,參見代碼以下:code


class ExamRoom {
public:
    ExamRoom(int N) {
        n = N;
    }
    
    int seat() {
        int start = 0, mx = 0, idx = 0;
        for (int i : spots) {
            if (start == 0) {
                if (mx < i - start) {
                    mx = i - start;
                    idx = 0;
                }
            } else {
                if (mx < (i - start + 1) / 2) {
                    mx = (i - start + 1) / 2;
                    idx = start + mx - 1;
                }
            }
            start = i + 1;
        }
        if (start > 0 && mx < n - start) {
            mx = n - start;
            idx = n - 1;
        }
        spots.insert(idx);
        return idx;
    }
    
    void leave(int p) {
        spots.erase(p);
    }

private:
    int n;
    set<int> spots;
};



討論:若這道題還有 follow up 的話,那麼博主能想到的就是變成二維的數組,這樣才更像一個真正的考場啊,畢竟大多數考場都不是隻有一排座位的。變成了二維的話,那麼周圍四面八方的人的距離都要考慮呢,想一想以爲還挺難的,你們有什麼想法的話,歡迎留言討論哈~htm



Github 同步地址:blog

https://github.com/grandyang/leetcode/issues/855



相似題目:

Maximize Distance to Closest Person



參考資料:

https://leetcode.com/problems/exam-room/

https://leetcode.com/problems/exam-room/discuss/139862/C%2B%2BJavaPython-Straight-Forward

https://leetcode.com/problems/exam-room/discuss/148595/Java-PriorityQueue-with-customized-object.-seat%3A-O(logn)-leave-O(n)-with-explanation



LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索