leetcode update

This commit is contained in:
gameloader 2024-09-28 16:35:37 +08:00
parent e6e6b222f8
commit 1293f69df3

View File

@ -14220,3 +14220,228 @@ public:
} }
}; };
``` ```
## day213 2024-09-27
### 731. My Calendar II
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 start and end that represents a booking on the half-open interval [start, end), the range of real numbers x such that start <= x < end.
Implement the MyCalendarTwo class:
MyCalendarTwo() Initializes the calendar object.
boolean book(int start, int end) 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.
![0927rcG0qD6TNhbk](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0927rcG0qD6TNhbk.png)
### 题解
本题仍然可以使用线段树求解,我们思考线段树的作用是什么,线段树使用了额外的空间保存了不断二分的区间的状态,从而对于有些区间问题,我们只需要知道这个区间拥有的某些性质即足以解决问题,没必要了解区间内的全部细节。这种区间对应了整体思想,将某些部分当作一个整体,用整体性质去求解。经典的线段树保存的是区间内全部数字的和,对于本题,我们只需修改区间保存的状态就可复用线段树解题。
本题中我们需要知道的是某个时间被访问过几次则可以记录每个时间被访问的次数对于区间我们可以记录该区间内这个访问次数的最大值。因为某个时间区间被预订后该区间的所有时间的访问次数都要加1因此仍然可以先将这个加1的状态保留在顶层的节点在需要时再向下探索并将状态传递下去。
则我们需要构造线段树其query查询的是某个区间的最大值update将区间所有节点均加1。遍历book数组对于每个预订判断对应区间的最大值是否等于2等于2则不能预定小于2则可以预定并更新区间值。
### 代码
```cpp
class MyCalendarTwo {
private:
struct Node {
Node* left;
Node* right;
int val;
int lazy;
Node() : left(nullptr), right(nullptr), val(0), lazy(0) {}
};
Node* root;
const int MAX_RANGE = 1e9;
void pushDown(Node* node, int start, int end) {
if (!node->left) node->left = new Node();
if (!node->right) node->right = new Node();
if (node->lazy) {
int mid = start + (end - start) / 2;
node->left->val += node->lazy;
node->left->lazy += node->lazy;
node->right->val += node->lazy;
node->right->lazy += node->lazy;
node->lazy = 0;
}
}
int query(Node* node, int start, int end, int l, int r) {
if (l <= start && end <= r) return node->val;
pushDown(node, start, end);
int mid = start + (end - start) / 2;
int res = 0;
if (l <= mid) res = max(res,query(node->left, start, mid, l, r));
if (r > mid) res = max(res,query(node->right, mid + 1, end, l, r));
return res;
}
void update(Node* node, int start, int end, int l, int r, int val) {
if (l <= start && end <= r) {
node->val += val;
node->lazy += val;
return;
}
pushDown(node, start, end);
int mid = start + (end - start) / 2;
if (l <= mid) update(node->left, start, mid, l, r, val);
if (r > mid) update(node->right, mid + 1, end, l, r, val);
node->val = max(node->left->val, node->right->val);
}
public:
MyCalendarTwo() {
root = new Node();
}
bool book(int start, int end) {
if (query(root, 0, MAX_RANGE, start, end - 1) >=2 ) {
return false;
}
update(root, 0, MAX_RANGE, start, end - 1, 1);
return true;
}
};
/**
* Your MyCalendarTwo object will be instantiated and called as such:
* MyCalendarTwo* obj = new MyCalendarTwo();
* bool param_1 = obj->book(start,end);
*/
```
### 总结
当然本题仍然可以通过暴力或者二分求解,下面给出暴力的示例代码
```cpp
class MyCalendarTwo {
vector<pair<int,int>> b;
vector<pair<int,int>>db;
public:
MyCalendarTwo() {
}
bool book(int start, int end) {
for(pair<int,int> x: db){
if(start<x.second && end>x.first) return false;
}
for(pair<int,int> x : b){
if(start<x.second && end>x.first){
db.push_back({max(start,x.first),min(end,x.second)});
}
}
b.push_back({start,end});
return true;
}
};
```
## day214 2024-09-28
### 641. Design Circular Deque
Design your implementation of the circular double-ended queue (deque).
Implement the MyCircularDeque class:
MyCircularDeque(int k) Initializes the deque with a maximum size of k.
boolean insertFront() Adds an item at the front of Deque. Returns true if the operation is successful, or false otherwise.
boolean insertLast() Adds an item at the rear of Deque. Returns true if the operation is successful, or false otherwise.
boolean deleteFront() Deletes an item from the front of Deque. Returns true if the operation is successful, or false otherwise.
boolean deleteLast() Deletes an item from the rear of Deque. Returns true if the operation is successful, or false otherwise.
int getFront() Returns the front item from the Deque. Returns -1 if the deque is empty.
int getRear() Returns the last item from Deque. Returns -1 if the deque is empty.
boolean isEmpty() Returns true if the deque is empty, or false otherwise.
boolean isFull() Returns true if the deque is full, or false otherwise.
![0928P8VO6toCeM2T](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0928P8VO6toCeM2T.png)
### 题解
本题是中等难度题,但题目本身逻辑比较简单,要实现双端循环链表,只需记录下链表的首部和尾部位置信息,链表的当前大小和最大容量按要求实现即可。可以用数组也可以用链表,本题中我使用数组实现。
### 代码
```cpp
class MyCircularDeque {
private:
vector<int> data;
int front;
int rear;
int size;
int capacity;
public:
MyCircularDeque(int k) : data(k), front(0), rear(0), size(0), capacity(k) {}
bool insertFront(int value) {
if (isFull()) return false;
data[front] = value;
if(size == 0){
rear = (front+1)%capacity;
}
front = (front - 1 + capacity) % capacity;
size++;
return true;
}
bool insertLast(int value) {
if (isFull()) return false;
data[rear] = value;
if (size == 0){
front = (rear - 1 + capacity) % capacity;
}
rear = (rear + 1) % capacity;
size++;
return true;
}
bool deleteFront() {
if (isEmpty()) return false;
front = (front + 1) % capacity;
size--;
return true;
}
bool deleteLast() {
if (isEmpty()) return false;
rear = (rear - 1 + capacity) % capacity;
size--;
return true;
}
int getFront() {
if (isEmpty()) return -1;
return data[(front+1)%capacity];
}
int getRear() {
if (isEmpty()) return -1;
return data[(rear - 1 + capacity) % capacity];
}
bool isEmpty() {
return size == 0;
}
bool isFull() {
return size == capacity;
}
};
```