題目描述:
實現一個 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毫秒。