妙用BST Sweep time line
Sweep time line
和刚刚的diff问题一样,只是问题颗粒不在是每个index, 而是index of interest, 在输入sparse的情况下避免了一秒一秒的数,而是event发生了再处理, 利用了bst的里面的key也是sorted的特性
用map的思路再来解 1109. Corporate Flight Bookings
和 1094. Car Pooling
区别在于, 1109: 定义为[i,j]. j时还没有下,j+1才算下车; 1094: 定义为[i,j) 在j已经下车了
class Solution {
vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {
map<int,int> timeline;
for (auto& b: bookings) {
int i = b[0], j = b[1], v = b[2];
timeline[i] += v;
timeline[j+1] -= v;
}
vector<int> ans(n);
ans[0] = timeline[1];
for (int i = 1; i < n; i++) {
ans[i] = ans[i-1] + timeline[i+1];
}
return ans;
}
};
class Solution {
public:
bool carPooling(vector<vector<int>>& trips, int capacity) {
map<int, int> timeline;
for (auto trip: trips) {
int val = trip[0], i = trip[1], j = trip[2];
timeline[i] += val;
timeline[j] -= val;
}
int count = 0;
int ans = 0;
for (auto&[e, c]: timeline) {
count += c;
ans = max(ans, count);
}
return ans <= capacity;
}
};
利用这个sweep line只记录diff的思想 可以解决一系列的meeting rooms/ My calendar/intervals问题
空间换时间
是不是和LRU, LFU里面的普通解法bst到bucket of linked list 一个意思? 都是一旦确定了range,则可以用bucket sort的思想把BST继续压平。利用空间换时间。
再看看meeting rooms系列
252. Meeting Rooms and 253. Meeting Rooms II
最直观的是也可以用sort by start,然后检查是否conflict的方式来做 I 但是同样的思路解II就那么容易,不如sweep line简便
class Solution {
public:
bool canAttendMeetings(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end());
for (int i = 1; i < intervals.size(); i++) {
int lastEnd = intervals[i-1][1];
int curStart = intervals[i][0];
if (lastEnd > curStart) return false;
}
return true;
}
bool canAttendMeetings(vector<vector<int>>& intervals) {
map<int,int> timeline;
for (auto e: intervals) {
timeline[e[0]]++;
timeline[e[1]]--;
}
int rooms = 0;
int ans = 0;
for (auto [e, room]: timeline) {
ans = max(ans, rooms += room);
}
return ans <= 1;
}
};
再看 My Calendar系列
729. My Calendar I
核心就用理由bst对start排序,找到start前一个和后一个 两个都不能conflict
class MyCalendar {
//prev next
//---| |---
// s---e
//overlap: s < prev.end or e > next.start
public:
MyCalendar() {}
bool book(int start, int end) {
auto next = books.lower_bound(start);
if (next != books.end() && next->first < end) return false;
if (next != books.begin() && start < prev(next)->second) return false;
books[start] = end;
return true;
}
private:
map<int,int> books;
};
但是万一要求的是可以有double booking,但是不能triple.怎么办? 这就得用sweep line了,book失败就revert之前的基数
731. My Calendar II
class MyCalendarTwo {
map<int, int> bookings;
public:
MyCalendarTwo() {}
bool book(int start, int end) {
bookings[start]++;
bookings[end]--;
int maxBooking = 0;
int curBooking = 0;
for (auto& [e, val]: bookings) {
maxBooking = max(maxBooking, curBooking += val);
if (maxBooking > 2) {
bookings[start]--;
bookings[end]++;
return false;
}
}
return true;
}
};
732. My Calendar III
直接求的就是最大值
class MyCalendarThree {
public:
MyCalendarThree() {
}
int book(int start, int end) {
bookings[start]++;
bookings[end]--;
int maxBooking = 0;
int curBooking = 0;
for (auto& [e, val]: bookings) {
maxBooking = max(maxBooking, curBooking += val);
}
return maxBooking;
}
private:
map<int,int> bookings;
};
TODO
https://leetcode.com/problems/merge-intervals/description/
https://leetcode.com/problems/insert-interval/description/
759. Employee Free Time
Written on December 29, 2021