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

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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值