Leetcode打卡:考场就坐

执行结果:通过

题目: 855 考场就坐

在考场里,有 n 个座位排成一行,编号为 0n - 1

当学生进入考场后,他必须坐在离最近的人最远的座位上。如果有多个这样的座位,他会坐在编号最小的座位上。(另外,如果考场里没有人,那么学生就坐在 0 号座位上。)

设计一个模拟所述考场的类。

实现 ExamRoom 类:

  • ExamRoom(int n) 用座位的数量 n 初始化考场对象。
  • int seat() 返回下一个学生将会入座的座位编号。
  • void leave(int p) 指定坐在座位 p 的学生将离开教室。保证座位 p 上会有一位学生。

示例 1:

复制代码
输入:
["ExamRoom", "seat", "seat", "seat", "seat", "leave", "seat"]
[[10], [], [], [], [], [4], []]
输出:
[null, 0, 9, 4, 2, null, 5]
解释:
ExamRoom examRoom = new ExamRoom(10);
examRoom.seat(); // 返回 0,房间里没有人,学生坐在 0 号座位。
examRoom.seat(); // 返回 9,学生最后坐在 9 号座位。
examRoom.seat(); // 返回 4,学生最后坐在 4 号座位。
examRoom.seat(); // 返回 2,学生最后坐在 2 号座位。
examRoom.leave(4);
examRoom.seat(); // 返回 5,学生最后坐在 5 号座位。

提示:

  1. 1 <= n <= 109
  2. 保证有学生正坐在座位 p 上。
  3. seatleave 最多被调用 104 次。

代码以及解题思路

代码:

复制代码
typedef struct mylink {
    int id;
    struct mylink *next;
} mylink;


typedef struct {
    int length;
    mylink* root;
} ExamRoom;
void print_obj(ExamRoom *obj)
{
    printf("%d ",obj->length);
    mylink* tmp=obj->root;
    while(tmp!=NULL)
    {
        printf("%d ",tmp->id);
        tmp=tmp->next;
    }
    printf("\n");
}


ExamRoom* examRoomCreate(int n) {
     ExamRoom* obj=malloc(sizeof(ExamRoom));
    obj->length=n;
    obj->root=NULL;
    return obj;

}

int examRoomSeat(ExamRoom* obj) {
    if(obj->root==NULL)
    {
        obj->root=malloc(sizeof(mylink));
        obj->root->id=0;
        obj->root->next=NULL;
        return 0;
    }
    int max=-1;
    if(obj->root->id!=0) max=obj->root->id;
    mylink* max_link_before=NULL;
    mylink* tmp=obj->root;
    int diff=0;
    while(tmp->next!=NULL)
    {   
        diff=(tmp->next->id - tmp->id)/2;
        if(diff>max)
        {
            max=diff;
            max_link_before=tmp;
        }
        tmp=tmp->next;
    }
    //tmp 为末尾时
    diff=obj->length -1 - tmp->id;
    if(diff>max)
    {
        max=diff;
        max_link_before=tmp;
    }
    if(max_link_before==NULL)
    {
        mylink* add=malloc(sizeof(mylink));
        add->id=0;
        add->next=obj->root;
        obj->root=add;
        return 0;
    }
    if(max_link_before->next==NULL)
    {
        max_link_before->next=malloc(sizeof(mylink));
        max_link_before->next->id=obj->length-1;
        max_link_before->next->next=NULL;
        return obj->length-1;
    }
    else
    {
        mylink* add=malloc(sizeof(mylink));
        add->id=max_link_before->id + max;
        add->next=max_link_before->next;
        max_link_before->next=add;
        return add->id;
    }

}

void examRoomLeave(ExamRoom* obj, int p) {
     mylink* tmp=obj->root;
    mylink* before=NULL;
    while(tmp!=NULL)
    {
        if(tmp->id==p)
        {
            if(before==NULL)
            {
                obj->root=tmp->next;
                free(tmp);
            }
            else
            {
                before->next=tmp->next;

                free(tmp);
            }
            return;
        }
        before=tmp;
        tmp=tmp->next;
    }

}

void examRoomFree(ExamRoom* obj) {
    mylink* tmp=obj->root;
    mylink* next;
    while(tmp!=NULL)
    {
        next=tmp->next;
        free(tmp);
        tmp=next;
    }
    free(obj);

}

解题思路:

1. 数据结构定义

  • mylink 结构体:表示链表中的一个节点,包含座位号 id 和指向下一个节点的指针 next
  • ExamRoom 结构体:表示考场,包含两个成员:length 表示考场总座位数,root 指向链表的头节点。
  • 作用:打印考场信息,包括总座位数和已分配的座位号。
  • 解题思路 :首先打印总座位数 length,然后遍历链表,打印每个节点的座位号 id

3. examRoomCreate 函数

  • 作用:创建一个新的考场对象。
  • 解题思路 :使用 malloc 分配 ExamRoom 结构体所需的内存,初始化 length 为传入的参数 nroot 初始化为 NULL(表示链表为空),最后返回创建的考场对象。

4. examRoomSeat 函数

  • 作用:在考场中分配一个座位,并返回分配的座位号。
  • 解题思路
    1. 如果链表为空(即还没有分配任何座位),则在链表头部插入一个座位号为 0 的节点,并返回 0
    2. 遍历链表,计算相邻座位之间的最大间距 max 和该间距前的节点 max_link_before
    3. 考虑链表末尾与最后一个座位之间的间距。
    4. 根据 max_link_before 的值,在最大间距处插入一个新节点:
      • 如果 max_link_beforeNULL,则在链表头部插入新节点。
      • 如果 max_link_before->nextNULL,则在链表尾部插入新节点。
      • 否则,在 max_link_beforemax_link_before->next 之间插入新节点。
    5. 新节点的座位号 idmax_link_before->id + max,然后返回新节点的座位号。

5. examRoomLeave 函数

  • 作用:释放一个座位。
  • 解题思路 :遍历链表,找到座位号为 p 的节点,并将其从链表中删除。如果要删除的节点是头节点,则更新头节点为下一个节点;否则,更新前一个节点的 next 指针,跳过要删除的节点。最后释放要删除的节点的内存。

6. examRoomFree 函数

  • 作用:释放考场对象及其占用的所有内存。
  • 解题思路:遍历链表,释放每个节点的内存,然后释放考场对象本身的内存。
相关推荐
乐闻x1 小时前
提升 React 应用性能:使用 React Profiler 进行性能调优
前端·javascript·react.js·性能优化
Q_Boom2 小时前
LeetCode 环形链表II:为什么双指针第二次会在环的入口相遇?
算法·leetcode·链表
SsummerC2 小时前
【leetcode100】括号生成
python·算法·leetcode
gotoc丶2 小时前
堆排序:力扣215.数组中的第K个大元素
javascript·数据结构·算法·leetcode·排序算法
一只_程序媛2 小时前
【leetcode hot 100 199】二叉树的右视图
算法·leetcode·职场和发展
一只_程序媛2 小时前
【leetcode hot 100 230】二叉搜索树中第K小的元素
算法·leetcode·职场和发展
双叶8365 小时前
(C语言)写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和(递归函数)
c语言·开发语言·数据结构·算法·游戏
大龄大专大前端5 小时前
JavaScript闭包的认识/应用/原理
前端·javascript·ecmascript 6
BineHello5 小时前
强化学习 - PPO控制无人机
人工智能·算法·自动驾驶·动态规划·无人机·强化学习
阿饼2405 小时前
算法——层序遍历和中序遍历构造二叉树
数据结构·算法