执行结果:通过
执行用时和内存消耗如下:
typedef struct {
int size;
int maxIntersection;
int** books;
// #ifdef DEBUG
// int runCount;
// #endif
} MyCalendarThree;
void insert(MyCalendarThree*, int, int, int, int);
int* binarySearch(int*, int, int);
MyCalendarThree* myCalendarThreeCreate() {
MyCalendarThree* newCal = (MyCalendarThree*)malloc(sizeof(MyCalendarThree));
newCal -> size = 0;
newCal -> maxIntersection = 0;
newCal -> books = (int**)malloc(sizeof(int*) * 2);
for (int i = 0; i < 2; i++) {
(newCal -> books)[i] = (int*)malloc(sizeof(int) * 400);
}
// #ifdef DEBUG
// newCal -> runCount = 0;
// #endif
return newCal;
}
int myCalendarThreeBook(MyCalendarThree* obj, int startTime, int endTime) {
//printf("New Process\n");
int* sLoc = binarySearch((obj -> books)[0], obj -> size, startTime);
int* eLoc = binarySearch((obj -> books)[1], obj -> size, startTime);
int initialSLoc = (int)(sLoc - (obj -> books)[0]);
int eeLoc = (int)(binarySearch((obj -> books)[1], obj -> size, endTime) - (obj -> books)[1]);
//printf("Initial: %d, %d\n", initialSLoc, (int)(eLoc - (obj -> books)[1]));
int count = initialSLoc - (int)(eLoc - (obj -> books)[1]) + 1;
// #ifdef DEBUG
// DEBUG(9);
// #endif
while (*sLoc < endTime) {
if (count > obj -> maxIntersection) obj -> maxIntersection = count;
if ((int)(sLoc - (obj -> books)[0]) >= obj -> size) {
break;
}
//printf("count: %d\n", count);
if (*sLoc < *eLoc) { sLoc++; count++; }
else { eLoc++; count--; }
}
if (count > obj -> maxIntersection) obj -> maxIntersection = count;
insert(obj, startTime, endTime, initialSLoc, eeLoc);
//printf("True, size=%d\n", obj -> size);
return obj -> maxIntersection;
}
void myCalendarThreeFree(MyCalendarThree* obj) {
for (int i = 0; i < 2; i++) {
free((obj -> books)[i]);
}
free(obj -> books);
free(obj);
}
/**
* Your MyCalendarThree struct will be instantiated and called as such:
* MyCalendarThree* obj = myCalendarThreeCreate();
* int param_1 = myCalendarThreeBook(obj, startTime, endTime);
* myCalendarThreeFree(obj);
*/
int* binarySearch(int* arr, int size, int target) {
int l = 0;
int r = size - 1;
while (l <= r) {
int i = (l + r) / 2;
if (target >= arr[i]) l = i + 1;
else r = i - 1;
}
return arr + l;
}
void insert(MyCalendarThree* obj, int startTime, int endTime, int sIdx, int eIdx) {
memmove(
(obj -> books)[0] + sIdx + 1,
(obj -> books)[0] + sIdx,
(obj -> size - sIdx) * sizeof(int)
);
memmove(
(obj -> books)[1] + eIdx + 1,
(obj -> books)[1] + eIdx,
(obj -> size - eIdx) * sizeof(int)
);
(obj -> books)[0][sIdx] = startTime;
(obj -> books)[1][eIdx] = endTime;
(obj -> size)++;
}
解题思路:
这段代码实现了一个名为 MyCalendarThree
的数据结构,用于跟踪在一段时间内(由开始时间和结束时间定义)的日程安排,并计算在任何给定时间点同时存在的最大日程数。下面是代码的思路分析:
数据结构定义
MyCalendarThree
结构体包含以下成员:int size
:当前已存储的日程数量。int maxIntersection
:在任何给定时间点同时存在的最大日程数。int** books
:一个二维数组,其中books[0]
存储所有日程的开始时间,books[1]
存储所有日程的结束时间。这样做可以方便地通过二分查找定位开始和结束时间。- 注释掉的
#ifdef DEBUG
部分用于调试,不在生产代码中启用。
函数实现
myCalendarThreeCreate
:- 分配并初始化
MyCalendarThree
结构体。 - 初始化
size
为 0,maxIntersection
为 0。 - 为
books
分配内存,初始化为存储两个包含 400 个整数的数组(预设大小,可以根据需要调整)。 - 返回创建的
MyCalendarThree
实例。
- 分配并初始化
binarySearch
:- 在给定的数组
arr
中查找第一个大于或等于target
的元素的指针。 - 使用二分查找算法提高查找效率。
- 返回指向找到的位置的指针。
- 在给定的数组
myCalendarThreeBook
:- 使用
binarySearch
找到新日程的开始时间和结束时间在books
中的位置。 - 计算初始的重叠数量(基于二分查找结果)。
- 遍历受影响的日程区间,更新
maxIntersection
,并根据需要调整count
(重叠数量)。 - 使用
insert
函数将新日程的开始和结束时间插入到books
中。 - 返回当前的
maxIntersection
。
- 使用
insert
:- 使用
memmove
函数为新的日程在books
数组中腾出空间。 - 将新日程的开始和结束时间插入到正确的位置。
- 更新
size
。
- 使用
myCalendarThreeFree
:- 释放
MyCalendarThree
结构体中分配的所有内存。
- 释放
使用流程
- 创建一个
MyCalendarThree
实例。 - 使用
myCalendarThreeBook
函数添加日程,并获取当前的maxIntersection
。 - 当不再需要时,使用
myCalendarThreeFree
释放MyCalendarThree
实例占用的内存。
关键点
- 时间复杂度:
binarySearch
:O(log n),其中 n 是books
中的日程数量。myCalendarThreeBook
:在最坏情况下,需要遍历所有日程来计算重叠,但由于使用了二分查找定位新日程的位置,所以整体复杂度仍较低。
- 空间复杂度:
- 预设了 400 个元素的数组来存储日程的开始和结束时间,这是根据预期使用情况进行的一个折衷。如果日程数量超过这个预设值,可能需要重新设计数据结构以动态扩展数组。