手机App防沉迷系统
2026/8/28 10:07:28 网站建设 项目流程

一、题目

题目描述
智能手机方便了我们生活的同时,也侵占了我们不少的时间。“手机App防沉迷系统”能够让我们每天合理地规划手机App使用时间,在正确的时间做正确的事。

它的大概原理是这样的:

在一天24小时内,可以注册每个App的允许使用时段
一个时间段只能使用一个App
App有优先级,数值越高,优先级越高。注册使用时段时,如果高优先级的App时间和低优先级的时段有冲突,则系统会自动注销低优先级的时段,如果App的优先级相同,则后添加的App不能注册。
请编程实现,根据输入数据注册App,并根据输入的时间点,返回时间点使用的App名称,如果该时间点没有注册任何App,请返回字符串“NA”。

输入描述
第一行表示注册的App数量 N(N ≤ 100)

第二部分包括 N 行,每行表示一条App注册数据

最后一行输入一个时间点,程序即返回该时间点使用的App

2
App1 1 09:00 10:00
App2 2 11:00 11:30
09:30

数据说明如下:

N行注册数据以空格分隔,四项数依次表示:App名称、优先级、起始时间、结束时间
优先级1~5,数字越大,优先级越高
时间格式 HH:MM,小时和分钟都是两位,不足两位前面补0
起始时间需小于结束时间,否则注册不上
注册信息中的时间段包含起始时间点,不包含结束时间点
输出描述
输出一个字符串,表示App名称,或NA表示空闲时间

示例1
输入

1
App1 1 09:00 10:00
09:30
1
2
3
输出

App1
1
说明

App1注册在9点到10点间,9点半可用的应用名是App1

示例2
输入

2
App1 1 09:00 10:00
App2 2 09:10 09:30
09:20
1
2
3
4
输出

App2
1
说明

APP1和App2的时段有冲突,App2优先级高,注册App2之后,App1自动注销,因此输出App2。

示例3
输入

2
App1 1 09:00 10:00
App2 2 09:10 09:30
09:50
1
2
3
4
输出

NA

二、代码

classApp:"""定义App类,用于存储App的相关信息"""def__init__(self,name,priority,start_time,end_time):self.name=name# App名称self.priority=priority# App优先级self.start_time=start_time# App允许使用的起始时间(以分钟为单位)self.end_time=end_time# App允许使用的结束时间(以分钟为单位)defconvert_time(time_str):""" 时间转换函数,将时间字符串转换为以分钟为单位的整数 :param time_str: 时间字符串,格式为"小时:分钟" :return: 转换后的分钟数 """hours,minutes=map(int,time_str.split(":"))# 将时间字符串按照":"分割并转换为整数returnhours*60+minutes# 将小时和分钟转换为分钟defmain():n=int(input())# 读取App数量apps=[]# 创建App列表,用于存储所有Appfor_inrange(n):# 循环读取每个App的信息,并创建App对象添加到列表中app_name,app_priority,app_start_time,app_end_time=input().split()app_priority=int(app_priority)app_start_time=convert_time(app_start_time)app_end_time=convert_time(app_end_time)apps.append(App(app_name,app_priority,app_start_time,app_end_time))query_time=convert_time(input())# 读取查询时间,并转换为分钟app_at_time="NA"# 初始化查询时间对应的App名称为"NA"# 创建已注册App列表registered_apps=[]forappinapps:ifapp.start_time>=app.end_time:continue# 如果起始时间不小于结束时间,则跳过# 遍历已注册的App列表,检查时间冲突foriinrange(len(registered_apps)-1,-1,-1):registered=registered_apps[i]# 如果存在时间冲突ifmax(app.start_time,registered.start_time)<min(app.end_time,registered.end_time):# 如果当前App的优先级高于已注册App的优先级ifapp.priority>registered.priority:registered_apps.pop(i)# 注销低优先级的Appelse:continue# 如果优先级不高,继续检查下一个已注册App# 将当前App添加到已注册App列表中registered_apps.append(app)# 遍历已注册App列表,找到查询时间对应的Appforappinregistered_apps:ifquery_time>=app.start_timeandquery_time<app.end_time:app_at_time=app.name# 更新查询时间对应的App名称break# 找到后退出循环print(app_at_time)# 输出查询时间对应的App名称if__name__=="__main__":main()

说明:

1、for _ in range(n):中的下划线_是一个常用的Python约定,表示一个临时变量,在循环中不会被使用。这里我们只需要循环n次,而不关心循环变量的值。

2、代码实现了App防沉迷系统的核心逻辑:按优先级处理时间冲突,高优先级App会覆盖低优先级App的注册时段。

3、时间处理:将"HH:MM"格式的时间转换为分钟数,便于比较和计算。

4、冲突检测:使用max(app.start_time, registered.start_time) < min(app.end_time, registered.end_time)判断两个时间段是否有重叠。

三、range() 函数详解

在上面的代码中,我们使用了for _ in range(n):来循环读取n个 App 的信息。range()是 Python 中一个非常基础且重要的内置函数,用于生成一个整数序列。

1. 基本语法

range()函数有三种调用形式:

  1. range(stop):生成从 0 到stop-1的整数序列。

    foriinrange(5):print(i)# 输出:0, 1, 2, 3, 4
  2. range(start, stop):生成从startstop-1的整数序列。

    foriinrange(2,6):print(i)# 输出:2, 3, 4, 5
  3. range(start, stop, step):生成从startstop-1,步长为step的整数序列。

    foriinrange(0,10,2):print(i)# 输出:0, 2, 4, 6, 8

2. 在本题中的应用

在我们的代码中:

for_inrange(n):# 读取每个 App 的信息
  • n是用户输入的 App 数量。
  • range(n)生成序列0, 1, 2, ..., n-1,循环会执行n次。
  • 下划线_是一个约定俗成的变量名,表示我们在循环中不需要使用这个循环变量(即不需要用到i的值),我们只关心循环执行的次数。

3. 重要特性

  • 惰性求值range()返回的是一个“range 对象”,而不是一个列表。它只在需要时才生成值,节省内存。
  • 不可变:range 对象是不可变的序列。
  • 支持索引:可以像列表一样使用索引访问。
    r=range(5,10)print(r[0])# 输出:5print(r[-1])# 输出:9

4. 常见用途

  1. 固定次数的循环for i in range(10):
  2. 生成索引:遍历列表时同时获取索引和值for i in range(len(lst)):
  3. 逆序循环for i in range(10, 0, -1):
  4. 生成数字列表list(range(5))得到[0, 1, 2, 3, 4]

5. 注意事项

  • range()的参数必须是整数。
  • stop值不包含在序列中(左闭右开区间)。
  • 如果start >= stopstep > 0,或者start <= stopstep < 0,则 range 对象为空。

理解range()函数对于编写 Python 循环至关重要,它是处理重复任务和控制流程的基础工具。

6. 代码中range(len(registered_apps) - 1, -1, -1)的解析

在本题的冲突检测代码中,有这样一行:

foriinrange(len(registered_apps)-1,-1,-1):

这行代码使用了range()函数的第三种形式range(start, stop, step),并且实现了逆序遍历列表的功能。下面详细解析:

参数含义
  • start = len(registered_apps) - 1:起始索引是列表最后一个元素的下标。
  • stop = -1:停止索引是 -1(不包含在序列中)。
  • step = -1:步长为 -1,表示每次递减 1。
生成的序列

假设registered_apps列表有 3 个元素(len(registered_apps) = 3),那么:

  • len(registered_apps) - 1 = 2
  • range(2, -1, -1)生成的序列是:2, 1, 0
为什么需要逆序遍历?

在冲突检测的逻辑中,我们需要遍历已注册的 App 列表,检查当前 App 与每个已注册 App 是否有时间冲突。如果发现冲突且当前 App 优先级更高,我们会从列表中移除(pop)那个已注册的低优先级 App。

关键点:如果我们在正向遍历(从 0 到 len-1)时移除元素,列表的索引会发生变化,可能导致跳过元素或索引越界。例如:

# 错误示例:正向遍历时移除元素foriinrange(len(lst)):if条件:lst.pop(i)# 移除后,后面所有元素的索引都减 1,但 i 还在增加,会跳过下一个元素

解决方案:逆序遍历。从最后一个元素开始向前遍历,这样即使移除当前元素,也不会影响前面尚未遍历到的元素的索引。

在本题中的具体作用
foriinrange(len(registered_apps)-1,-1,-1):registered=registered_apps[i]ifmax(app.start_time,registered.start_time)<min(app.end_time,registered.end_time):ifapp.priority>registered.priority:registered_apps.pop(i)# 安全移除,因为 i 后面的元素(索引更大的)已经遍历过了else:continue
  1. 从后往前检查:先检查最近注册的 App(列表末尾),符合“后添加的 App 不能注册(如果优先级相同)”的规则。
  2. 安全移除pop(i)移除元素时,不会影响尚未遍历到的、索引更小的元素。
  3. 效率:逆序遍历在需要移除元素时更安全、更直观。
其他逆序遍历写法
  • for i in reversed(range(len(registered_apps))):使用reversed()函数,可读性更好。
  • for i in range(len(registered_apps)-1, -1, -1):直接使用range(),更底层、更明确。

理解这种逆序遍历的技巧对于处理需要修改列表的循环场景非常重要。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询