-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
157 lines (134 loc) · 4.94 KB
/
main.cpp
File metadata and controls
157 lines (134 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Source: https://leetcode.com/problems/my-calendar-ii
// Title: My Calendar II
// Difficulty: Medium
// Author: Mu Yang <http://muyang.pro>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// You are implementing a program to use as your calendar. We can add a new event if adding the event will not cause a **triple booking**.
//
// A **triple booking** happens when three events have some non-empty intersection (i.e., some moment is common to all the three events.).
//
// The event can be represented as a pair of integers `startTime` and `endTime` that represents a booking on the half-open interval `[startTime, endTime)`, the range of real numbers `x` such that `startTime <= x < endTime`.
//
// Implement the `MyCalendarTwo` class:
//
// - `MyCalendarTwo()` Initializes the calendar object.
// - `boolean book(int startTime, int endTime)` Returns `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.
//
// **Example 1:**
//
// ```
// Input:
// ["MyCalendarTwo", "book", "book", "book", "book", "book", "book"]
// [[], [10, 20], [50, 60], [10, 40], [5, 15], [5, 10], [25, 55]]
//
// Output:
// [null, true, true, true, false, true, true]
//
// Explanation:
// MyCalendarTwo myCalendarTwo = new MyCalendarTwo();
// myCalendarTwo.book(10, 20); // return True, The event can be booked.
// myCalendarTwo.book(50, 60); // return True, The event can be booked.
// myCalendarTwo.book(10, 40); // return True, The event can be double booked.
// myCalendarTwo.book(5, 15); // return False, The event cannot be booked, because it would result in a triple booking.
// myCalendarTwo.book(5, 10); // return True, The event can be booked, as it does not use time 10 which is already double booked.
// myCalendarTwo.book(25, 55); // return True, The event can be booked, as the time in [25, 40) will be double booked with the third event, the time [40, 50) will be single booked, and the time [50, 55) will be double booked with the second event.
// ```
//
// **Constraints:**
//
// - `0 <= start < end <= 10^9`
// - At most `1000` calls will be made to `book`.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <algorithm>
#include <map>
#include <utility>
#include <vector>
using namespace std;
// Brute-Force
class MyCalendarTwo {
using Range = pair<int, int>; // start, end
vector<Range> events;
public:
MyCalendarTwo() {}
bool book(int newStart, int newEnd) {
// Find overlapping events
auto overlaps = vector<Range>();
for (const auto [oldStart, oldEnd] : events) {
if (newStart < oldEnd && oldStart < newEnd) {
overlaps.push_back(Range{max(newStart, oldStart), min(newEnd, oldEnd)});
}
}
// Sort the overlaps and check double booking
sort(overlaps.begin(), overlaps.end());
for (int i = 1; i < overlaps.size(); ++i) {
const auto [prevStart, prevEnd] = overlaps[i - 1];
const auto [currStart, currEnd] = overlaps[i];
if (prevEnd > currStart) return false;
}
events.push_back(Range{newStart, newEnd});
return true;
}
};
// Brute-Force (Optimized)
//
// Instead of finding overlaps in on booking,
// we can also store the overlaps in an array.
class MyCalendarTwo2 {
struct Range {
int start;
int end;
};
vector<Range> events;
vector<Range> overlaps;
public:
MyCalendarTwo2() {}
bool book(int newStart, int newEnd) {
// Find overlap to with existing overlaps
for (const auto [overlapStart, overlapEnd] : overlaps) {
if (newStart < overlapEnd && overlapStart < newEnd) return false;
}
// Insert new overlaps
for (const auto [eventStart, eventEnd] : events) {
if (newStart < eventEnd && eventStart < newEnd) {
overlaps.push_back(Range{max(newStart, eventStart), min(newEnd, eventEnd)});
}
}
// Insert new event
events.push_back(Range{newStart, newEnd});
return true;
}
};
// Line Sweep + Tree Map
//
// Stores the start/end time in the tree map.
//
// We first try to book the new event.
// Next loop through all data and check if there is triple booking (and rollback).
//
// Note that this solution is better for k-fold booking when k is larger.
class MyCalendarTwo3 {
map<int, int> deltas; // time -> event count delta
public:
MyCalendarTwo3() {}
bool book(int startTime, int endTime) {
// Try to book new event
deltas[startTime]++;
deltas[endTime]--;
// Loop
int eventCount = 0;
for (const auto [time, delta] : deltas) {
eventCount += delta;
// Triple booking. Rollback.
if (eventCount >= 3) {
deltas[startTime]--;
deltas[endTime]++;
if (deltas[startTime] == 0) deltas.erase(startTime);
return false;
}
// Early stop
if (time >= endTime) break;
}
return true;
}
};