LeetCode:732. 我的日程安排表 III

題目描述:

實現一個 MyCalendar 類來存放你的日程安排,你可以一直添加新的日程安排。

MyCalendar 有一個 book(int start, int end)方法。它意味着在start到end時間內增加一個日程安排,注意,這裏的時間是半開區間,即 [start, end), 實數 x 的範圍爲,  start <= x < end。

當 K 個日程安排有一些時間上的交叉時(例如K個日程安排都在同一時間內),就會產生 K 次預訂。

每次調用 MyCalendar.book方法時,返回一個整數 K ,表示最大的 K 次預訂。

請按照以下步驟調用MyCalendar 類: MyCalendar cal = new MyCalendar(); MyCalendar.book(start, end)

樣例輸入輸出:

示例 1:

MyCalendarThree();
MyCalendarThree.book(10, 20); // returns 1
MyCalendarThree.book(50, 60); // returns 1
MyCalendarThree.book(10, 40); // returns 2
MyCalendarThree.book(5, 15); // returns 3
MyCalendarThree.book(5, 10); // returns 3
MyCalendarThree.book(25, 55); // returns 3
解釋:
前兩個日程安排可以預訂並且不相交,所以最大的K次預訂是1。
第三個日程安排[10,40]與第一個日程安排相交,最高的K次預訂爲2。
其餘的日程安排的最高K次預訂僅爲3。
請注意,最後一次日程安排可能會導致局部最高K次預訂爲2,但答案仍然是3,原因是從開始到最後,時間[10,20],[10,40]和[5,15]仍然會導致3次預訂。

說明:

    每個測試用例,調用 MyCalendar.book 函數最多不超過 400次。
    調用函數 MyCalendar.book(start, end)時, start 和 end 的取值範圍爲 [0, 10^9]。

思路:

可以把這些預定的時間段看作是平鋪在一個座標上的線段,如果遇到一個開始,這個座標上就會多一個預定的行程,遇到一個結束,座標上就會少一個行程,那麼我們可以將這些時間點存放起來,開始標記爲1,結束標記爲-1,按順序排放後遍歷求和,期間遇到的最大值就是最大預定次數。

代碼如下:

class MyCalendarThree
{
public:
    map<int,int>records;
    map<int,int>::iterator it;
    int maxa=0;
    MyCalendarThree()
    {

    }
    int book(int start,int end)
    {
        int ans=0;
        it=records.find(start);
        if (it==records.end())
            records.insert(make_pair(start,1));
        else
            records[start]++;
        it=records.find(end);
        if(it==records.end())
            records.insert(make_pair(end,-1));
        else
            records[end]--;
        for(auto p:records)
        {
            maxa=max(maxa,ans+=p.second);
        }
        return maxa;
    }
};

值得注意的是,這道題我一開始用vector存儲,然後利用快排對其排序然後發現會超時,用STLmap來實現存儲與排序就不會超時了,因爲快排時間複雜度nlog(n),而map是自帶排序功能的,一般是基於紅黑數完成的,插入數據與查找數據的複雜度均爲log(n)。還有在map中利用迭代器對value進行修改效率要比直接利用key值修改低的多,上面代碼原本用迭代器修改用語句it->second++花了280毫秒,而直接利用key值records[start]++則只用了180毫秒。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章