Leetcode打卡:考场就坐
执行结果:通过
题目: 855 考场就坐
在考场里,有 n
个座位排成一行,编号为 0
到 n - 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 <= n <= 109
- 保证有学生正坐在座位
p
上。 seat
和leave
最多被调用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
指向链表的头节点。
2. print_obj
函数
- 作用:打印考场信息,包括总座位数和已分配的座位号。
- 解题思路:首先打印总座位数
length
,然后遍历链表,打印每个节点的座位号id
。
3. examRoomCreate
函数
- 作用:创建一个新的考场对象。
- 解题思路:使用
malloc
分配ExamRoom
结构体所需的内存,初始化length
为传入的参数n
,root
初始化为NULL
(表示链表为空),最后返回创建的考场对象。
4. examRoomSeat
函数
- 作用:在考场中分配一个座位,并返回分配的座位号。
- 解题思路:
- 如果链表为空(即还没有分配任何座位),则在链表头部插入一个座位号为
0
的节点,并返回0
。 - 遍历链表,计算相邻座位之间的最大间距
max
和该间距前的节点max_link_before
。 - 考虑链表末尾与最后一个座位之间的间距。
- 根据
max_link_before
的值,在最大间距处插入一个新节点:- 如果
max_link_before
为NULL
,则在链表头部插入新节点。 - 如果
max_link_before->next
为NULL
,则在链表尾部插入新节点。 - 否则,在
max_link_before
和max_link_before->next
之间插入新节点。
- 如果
- 新节点的座位号
id
为max_link_before->id + max
,然后返回新节点的座位号。
- 如果链表为空(即还没有分配任何座位),则在链表头部插入一个座位号为
5. examRoomLeave
函数
- 作用:释放一个座位。
- 解题思路:遍历链表,找到座位号为
p
的节点,并将其从链表中删除。如果要删除的节点是头节点,则更新头节点为下一个节点;否则,更新前一个节点的next
指针,跳过要删除的节点。最后释放要删除的节点的内存。
6. examRoomFree
函数
- 作用:释放考场对象及其占用的所有内存。
- 解题思路:遍历链表,释放每个节点的内存,然后释放考场对象本身的内存。