leetcode: 729. My Calendar I,731. My Calendar II

来源:互联网 发布:我的知颜母亲大学写生 编辑:程序博客网 时间:2024/04/30 06:28

Implement a MyCalendar class to store your events. A new event can be added if adding the event will not cause a double booking.

Your class will have the method, book(int start, int end). Formally, this represents a booking on the half open interval [start, end), the range of real numbers x such that start <= x < end.

A double booking happens when two events have some non-empty intersection (ie., there is some time that is common to both events.)

For each call to the method MyCalendar.book, return true if the event can be added to the calendar successfully without causing a double booking. Otherwise, return false and do not add the event to the calendar.

Your class will be called like this: MyCalendar cal = new MyCalendar(); MyCalendar.book(start, end)
Example 1:
MyCalendar();
MyCalendar.book(10, 20); // returns true
MyCalendar.book(15, 25); // returns false
MyCalendar.book(20, 30); // returns true
Explanation:
The first event can be booked. The second can’t because time 15 is already booked by another event.
The third event can be booked, as the first event takes every time less than 20, but not including 20.

这题其实挺简单,逐一比较每一个预定就行,判断是否有交集,我用了两个链表来维持每一次预定的起始和结束,然后保持起始时间递增。其实不用保序也可以。都是线性时间,复杂度一致。

class MyCalendar {private:    list<int> st;    list<int> ed;public:    MyCalendar() {    }    bool book(int start, int end) {        list<int>::iterator it1, it2;        it1 = st.begin();        it2 = ed.begin();        while (it1 != st.end() && it2 != ed.end()) {            if (start == *it1) return false;            if (start > *it1) {                if (start < *it2) return false;                else it1++, it2++;            }            else {                if (end > *it1) return false;                else {                    st.insert(it1, start);                    ed.insert(it2, end);                    return true;                }            }        }        st.insert(it1, start);        ed.insert(it2, end);        return true;    }};

不用维持顺序的话,可以做的更简单。
两次预定之间的关系如下
这里写图片描述

所以overlap的区间可以写成:

(max(b.first, start), min(b.second, end));

简便的扫描算法可以是:

class MyCalendar {private:    vector<pair<int, int>> books;public:    bool book(int start, int end) {        for (auto b : books) {            if (max(b.first, start) < min(b.second, end)) return false;        }        books.push_back(make_pair(start, end));        return true;    }};

延伸题:
可以允许两次重叠,不能有三次重叠。
Implement a MyCalendarTwo class to store your events. A new event can be added if adding the event will not cause a triple booking.

Your class will have one method, book(int start, int end). Formally, this represents a booking on the half open interval [start, end), the range of real numbers x such that start <= x < end.

A triple booking happens when three events have some non-empty intersection (ie., there is some time that is common to all 3 events.)

For each call to the method MyCalendar.book, return true if the event can be added to the calendar successfully without causing a triple booking. Otherwise, return false and do not add the event to the calendar.

Your class will be called like this: MyCalendar cal = new MyCalendar(); MyCalendar.book(start, end)

这题其实比上一题难一点。可以借助上一题,将已有的overlap区间提出来,然后存在MyCalendar I 里面。如果再重叠,就是第三次重叠了。

class MyCalendarTwo {private:    vector<pair<int, int>> books;public:    MyCalendarTwo() {    }    bool book(int start, int end) {        MyCalendar overlaps;        for (auto b : books) {            if (max(b.first, start) < min(b.second, end)) {                if (!overlaps.book(max(b.first, start), min(b.second, end))) return false;            }        }        books.push_back({start, end});        return true;    }};
原创粉丝点击