📜  门|门模拟 2017 |问题 11(1)

📅  最后修改于: 2023-12-03 14:58:37.764000             🧑  作者: Mango

门|门模拟 2017 |问题 11

简介

这是一道门禁系统的题目,需要根据一系列的开门操作记录判断是否存在非法入侵,并输出非法入侵者的ID。

题目描述

题目会给出一组开门操作的记录,记录包含三个部分:刷卡记录的时间、刷卡者的ID、操作类型(进门或出门)。操作类型只有两种,进门为 "IN",出门为 "OUT"。记录按时间顺序排列。

需要编写一个程序来判断是否存在非法入侵,并输出非法入侵者的ID。每个ID只需要输出一次,而且需要按ID的字典序从小到大排列。

代码思路

假设每个人的出入门操作都是一一匹配的,那么我们可以用一个字典 door 来记录每个人的进出门操作次数。

每次拿到刷卡记录后,我们可以根据操作类型来更新字典中每个人的进出门次数。如果在更新之前发现某个人的进出门次数已经不匹配了,那么这个人就是非法进入者,需要记录下来。

最后将所有的非法进入者的ID按字典序排序后输出。

具体实现见代码注释。

代码实现
def check_illegal_access(records):
    """
    :param records: 刷卡记录
    :return: 非法进入者的ID
    """
    door = {}
    illegal_access = set()

    for record in records:
        time, id, action = record.split()
        if id not in door:
            door[id] = {"in": 0, "out": 0}
        door[id][action] += 1

        # 如果某个人的出入门次数不匹配,说明有非法进入
        if door[id]["out"] > door[id]["in"]:
            illegal_access.add(id)

    # 按字典序排序输出结果
    return sorted(illegal_access)
使用示例
records = [
    "100001 08:30:00 IN",
    "100001 12:30:00 OUT",
    "100002 09:10:00 IN",
    "100002 11:00:00 OUT",
    "100001 13:00:00 IN",
    "100001 18:00:00 OUT"
]

print(check_illegal_access(records))

输出:

['100002']
时间复杂度

假设刷卡记录有 n 条,其中有 m 个不同的人刷过卡,时间复杂度为 O(n·log(m)),主要来自于最后排序的操作。实际上,如果只需要判断是否有非法进入者,可以直接把 illegal_access 数据结构换成 set,并去掉最后的排序操作,时间复杂度可以做到 O(n)。