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 实例的内存。

思路总结

  • 使用双向链表来管理考场的座位,便于在任意位置插入和删除座位。
  • 分配座位时,优先考虑最大化相邻座位间的间隔,以尽可能均匀地分布考生。
  • 释放座位时,需要更新链表结构,保持链表的完整性。
  • 在使用完毕后,需要释放所有分配的内存资源,避免内存泄漏。
相关推荐
deli0074 分钟前
DLA 枝晶生长实测:5000 个粒子集体停摆之后,分形维数收敛到 1.70
前端
IT_陈寒13 分钟前
Redis卡顿的锅,这次真不是大key的错
前端·人工智能·后端
可乐鸡翅yeah_20 分钟前
video.js 集成 hls.js 开发 M3U8 播放器,新手高频踩坑
开发语言·前端·javascript·后端·ecmascript·m3u8·音视频在线播放
程序猿追1 小时前
HarmonyOS 6 上做个极简浏览器:Web 组件 + 前进后退 + 加载进度
前端·华为·harmonyos
沐沐师1 小时前
Mybatis 框架教程
前端
三天不学习1 小时前
Tailwind CSS 快速入门(2026 版):从 v4 零配置上手,到「该不该用、怎么用好」的选型实战
前端·css·tailwind
明月_清风1 小时前
面对陌生的 GitHub 项目无从下手?这 4 个网站帮你快速读懂源码
前端·后端·github
htzyl2062 小时前
前端阶梯——第九章、颜色、文本与背景
前端·css
zhangzeyuaaa2 小时前
Ruby `require` 完全指南:从 `$LOAD_PATH` 到 `require_relative`
服务器·前端·ruby
htzyl2062 小时前
前端阶梯——第八章、CSS入门与选择器
前端·css