Leecode刷题C语言之我的日程安排表③

执行结果:通过

执行用时和内存消耗如下:

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 部分用于调试,不在生产代码中启用。

函数实现

  1. myCalendarThreeCreate
    • 分配并初始化 MyCalendarThree 结构体。
    • 初始化 size 为 0,maxIntersection 为 0。
    • books 分配内存,初始化为存储两个包含 400 个整数的数组(预设大小,可以根据需要调整)。
    • 返回创建的 MyCalendarThree 实例。
  2. binarySearch
    • 在给定的数组 arr 中查找第一个大于或等于 target 的元素的指针。
    • 使用二分查找算法提高查找效率。
    • 返回指向找到的位置的指针。
  3. myCalendarThreeBook
    • 使用 binarySearch 找到新日程的开始时间和结束时间在 books 中的位置。
    • 计算初始的重叠数量(基于二分查找结果)。
    • 遍历受影响的日程区间,更新 maxIntersection,并根据需要调整 count(重叠数量)。
    • 使用 insert 函数将新日程的开始和结束时间插入到 books 中。
    • 返回当前的 maxIntersection
  4. insert
    • 使用 memmove 函数为新的日程在 books 数组中腾出空间。
    • 将新日程的开始和结束时间插入到正确的位置。
    • 更新 size
  5. myCalendarThreeFree
    • 释放 MyCalendarThree 结构体中分配的所有内存。

使用流程

  • 创建一个 MyCalendarThree 实例。
  • 使用 myCalendarThreeBook 函数添加日程,并获取当前的 maxIntersection
  • 当不再需要时,使用 myCalendarThreeFree 释放 MyCalendarThree 实例占用的内存。

关键点

  • 时间复杂度
    • binarySearch:O(log n),其中 n 是 books 中的日程数量。
    • myCalendarThreeBook:在最坏情况下,需要遍历所有日程来计算重叠,但由于使用了二分查找定位新日程的位置,所以整体复杂度仍较低。
  • 空间复杂度
    • 预设了 400 个元素的数组来存储日程的开始和结束时间,这是根据预期使用情况进行的一个折衷。如果日程数量超过这个预设值,可能需要重新设计数据结构以动态扩展数组。
相关推荐
可喜~可乐18 分钟前
总线通信接口I²C以及SPI入门指南:从原理到实践
c语言·stm32·单片机·嵌入式硬件
矮油0_o2 小时前
Ⅱ.INTRODUCTION TO CUDA C (CUDA C 入门)
c语言·开发语言·gpu算力·cuda c
麻瓜老宋4 小时前
【手搓一个脚本语言】七、用C语言抽象语法树AST实现一个可交互运行的表达式计算器
c语言·开发语言·数据结构·算法
最后一个bug5 小时前
linuxC语言从Http服务器上获得文件
linux·服务器·c语言·arm开发·嵌入式硬件
小白的登仙路14 小时前
进程间通讯
linux·c语言·进程间通讯
graceyun16 小时前
牛客网刷题 ——C语言初阶(6指针)——字符逆序
c语言·开发语言
graceyun16 小时前
牛客网刷题 ——C语言初阶(5操作符)——OR76 两个整数二进制位不同个数
c语言·开发语言
graceyun17 小时前
C语言初阶习题(6指针)【21】打印水仙花数
c语言·开发语言
Rossy Yan18 小时前
【C语言程序设计——入门】C语言入门与基础语法(头歌实践教学平台习题)【合集】
c语言·开发语言·入门·头歌实践教学平台·合集
don't_be_bald19 小时前
数据结构与算法-顺序表
c语言·开发语言·数据结构·学习·链表