Leecode刷题C语言之考场就座

执行结果:通过

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

typedef struct _Seat {
    int id;
    struct _Seat* prev;
    struct _Seat* next;
} Seat;

typedef struct _ExamRoom {
    int     cap;
    int     cnt;
    Seat* head;
} ExamRoom;

ExamRoom* examRoomCreate(int n) {
    ExamRoom* ret = (ExamRoom * )calloc(sizeof(ExamRoom), 1);
    ret->cap = n;
    return ret;
}

int examRoomSeat(ExamRoom* obj) {
    Seat* seat = (Seat * )calloc(sizeof(Seat), 1);
    Seat* p;
    Seat* maxGapSeat = 0;
    int   maxGap = 0;
    int   i, gap;

    switch (obj->cnt) {
    case 0:
        seat->id = 0;
        obj->head = seat;
        break;
    case 1:
        if (obj->cap - 1 - obj->head->id > obj->head->id) {
            seat->id = obj->cap - 1;
            obj->head->next = seat;
            seat->prev = obj->head;
        }
        else {
            seat->id = 0;
            seat->next = obj->head;
            obj->head->prev = seat;
            obj->head = seat;
        }
        break;
    default:
        for (i = 0, p = obj->head; i < obj->cnt; i++, p = p->next) {
            if ((i == 0) && (p->id != 0)) {
                gap = p->id;
                maxGap = gap;
                maxGapSeat = 0;
            }
            else if (i == obj->cnt - 1) {
                if (p->id != obj->cap - 1) {
                    gap = obj->cap - 1 - p->id;
                    if (maxGap < gap) {
                        maxGap = gap;
                        maxGapSeat = p;
                    }
                }
                else {
                    gap = (p->prev->id + p->id) / 2 - p->prev->id;
                    if (maxGap < gap) {
                        maxGap = gap;
                        maxGapSeat = p->prev;
                    }
                }
            }
            else {
                gap = (p->next->id + p->id) / 2 - p->id;
                if (maxGap < gap) {
                    maxGap = gap;
                    maxGapSeat = p;
                }
            }
        }

        if (maxGapSeat == 0) {
            seat->id = 0;
            seat->next = obj->head;
            obj->head->prev = seat;
            obj->head = seat;
        }
        else {
            seat->id = maxGapSeat->id + maxGap;
            seat->prev = maxGapSeat;
            if (maxGapSeat->next) {
                seat->next = maxGapSeat->next;
                maxGapSeat->next->prev = seat;
            }
            maxGapSeat->next = seat;
        }
        break;
    }
    obj->cnt++;
    return seat->id;
}

void examRoomLeave(ExamRoom* obj, int seat) {
    Seat* p;
    int i;
    for (i = 0, p = obj->head; i < obj->cnt; i++, p = p->next) {
        if (p->id == seat) {
            if (i == 0) {
                obj->head = p->next;
                if (p->next) {
                    p->next->prev = 0;
                }
            }
            else if (i == obj->cnt - 1) {
                p->prev->next = 0;
            }
            else {
                p->prev->next = p->next;
                p->next->prev = p->prev;
            }
            free(p);
            obj->cnt--;
            break;
        }
    }
}

void examRoomFree(ExamRoom* obj) {

}

解题思路如下 :

这段代码实现了一个简单的考场座位管理系统,其中包含了创建考场、分配座位、释放座位和释放考场资源的功能。下面是代码的具体思路:

结构体定义

  1. Seat 结构体

    • int id:座位编号。
    • struct _Seat* prev:指向前一个座位的指针。
    • struct _Seat* next:指向下一个座位的指针。

    这个结构体用于表示考场中的座位,座位之间通过双向链表连接。

  2. ExamRoom 结构体

    • int cap:考场容量,即最大座位数。
    • int cnt:当前已分配的座位数。
    • Seat* head:指向考场座位链表的头节点的指针。

    这个结构体用于表示整个考场,包含考场的基本信息和座位链表。

函数实现

  1. examRoomCreate(int n)
    • 创建一个新的 ExamRoom 实例。
    • 分配内存并初始化,设置考场的容量为 n
    • 返回创建的 ExamRoom 实例的指针。
  2. *examRoomSeat(ExamRoom obj)**:
    • 在考场 obj 中分配一个座位。
    • 如果考场为空(cnt == 0),则分配第一个座位(id = 0)。
    • 如果考场中有一个座位(cnt == 1),则根据剩余空间的大小,在头或尾分配第二个座位。
    • 如果考场中有多个座位(cnt > 1),则遍历座位链表,找到相邻座位间最大间隔的位置,并在此位置分配一个新座位。间隔的计算考虑了首尾座位之间的间隔。
    • 更新考场中的座位数 cnt
    • 返回新分配座位的编号。
  3. *examRoomLeave(ExamRoom obj, int seat)**:
    • 释放考场 obj 中的指定座位 seat
    • 遍历座位链表,找到座位编号为 seat 的座位节点。
    • 根据该座位在链表中的位置,更新前后座位的指针,将其从链表中移除。
    • 释放该座位节点的内存。
    • 更新考场中的座位数 cnt
  4. *examRoomFree(ExamRoom obj)**:
    • 释放考场 obj 的所有资源。
    • 此函数在提供的代码中是空的,需要实现遍历座位链表并释放所有座位节点的内存,最后释放 ExamRoom 实例的内存。

思路总结

  • 使用双向链表来管理考场的座位,便于在任意位置插入和删除座位。
  • 分配座位时,优先考虑最大化相邻座位间的间隔,以尽可能均匀地分布考生。
  • 释放座位时,需要更新链表结构,保持链表的完整性。
  • 在使用完毕后,需要释放所有分配的内存资源,避免内存泄漏。
相关推荐
恋猫de小郭30 分钟前
再聊 Flutter Riverpod ,注解模式下的 Riverpod 有什么特别之处,还有发展方向
android·前端·flutter
Aress"32 分钟前
【2025前端高频面试题——系列一之MVC和MVVM】
前端·mvc
Json____37 分钟前
好玩的谷歌浏览器插件-自定义谷歌浏览器光标皮肤插件-Chrome 的自定义光标
前端·chrome·谷歌插件·谷歌浏览器插件·光标皮肤·自定义光标
蜡笔小新星2 小时前
Flask项目框架
开发语言·前端·经验分享·后端·python·学习·flask
马剑威(威哥爱编程)2 小时前
C语言操作MySQL从入门到精通
c语言·mysql·adb
Fantasywt5 小时前
THREEJS 片元着色器实现更自然的呼吸灯效果
前端·javascript·着色器
IT、木易6 小时前
大白话JavaScript实现一个函数,将字符串中的每个单词首字母大写。
开发语言·前端·javascript·ecmascript
Mr.NickJJ7 小时前
JavaScript系列06-深入理解 JavaScript 事件系统:从原生事件到 React 合成事件
开发语言·javascript·react.js
Kurbaneli8 小时前
深入理解 C 语言函数的定义
linux·c语言·ubuntu
Archer1948 小时前
C语言——链表
c语言·开发语言·链表