[[], [1], [100], [3001], [3002]]
转换为 RecentCounter
类的 ping
方法的调用,并得到输出结果 [None, 1, 2, 3, 3]
,你需要编写一段代码来模拟这个过程。下面是一个 Python 代码示例,它创建了 RecentCounter
类的实例,并按照给定的输入序列调用 ping
方法,然后收集每次调用的返回值。
from collections import deque
class RecentCounter:
def __init__(self):
self.requests = deque()
def ping(self, t: int) -> int:
self.requests.append(t)
# 移除不在 [t-3000, t] 范围内的请求
while self.requests and self.requests[0] < t - 3000:
self.requests.popleft()
return len(self.requests)
# 模拟输入
operations = [[], [1], [100], [3001], [3002]]
# 初始化 RecentCounter 实例
recent_counter = RecentCounter()
# 存储输出结果
results = []
# 遍历操作序列
for operation in operations:
if operation: # 如果操作列表不为空,调用 ping 方法
results.append(recent_counter.ping(operation[0]))
else: # 否则,添加 None 表示实例化操作没有返回值
results.append(None)
# 打印输出结果
print(results) # 输出应为 [None, 1, 2, 3, 3]
解题思路:
方法选择:
选用的方法是使用一个队列来维护时间戳,队列中存储的是请求对应的时间点。当新请求到来时,我们将该时间点加入队列;同时移除那些不在最近3000毫秒内的请求时间点。这样,队列中的所有时间点就代表了最近3000毫秒内的所有请求,队列的长度即为我们要求的结果。
解题过程:
- 初始化一个队列来存储请求的时间戳。
- 每次调用
ping
方法时,首先将当前时间戳加入队列。 - 然后检查队列的头部,如果队列头部的时间戳与当前时间戳的差值大于3000毫秒,则将其移除队列。
- 重复步骤3,直到队列头部的时间戳与当前时间戳的差值不超过3000毫秒或队列为空。
- 返回此时队列的长度,即为最近3000毫秒内的请求数量。
具体运用:
- 使用
deque
(双端队列)作为存储结构,因为它允许我们在两端快速地添加和移除元素。 - 在
ping
方法中,使用append
操作将新的时间戳添加到队列的末尾。 - 使用
popleft
操作移除队列头部的时间戳,直到满足时间要求或队列变空。 - 返回队列的长度,这个长度就是最近3000毫秒内的请求数。
复杂度分析:
时间复杂度:O(N),其中N是调用
ping
方法的次数。在最坏的情况下,每次ping
调用都可能需要移除队列中的所有元素。但在平均情况下,由于请求是均匀到达的,所以每次ping
调用平均只需要移除一个元素,时间复杂度接近O(1)。空间复杂度:O(N),最坏情况下,队列中可能需要存储所有请求的时间戳,其中N是调用
ping
方法的次数。在实际应用中,队列的大小通常不会超过3000毫秒内请求的数量,因此空间复杂度通常也是O(1)。
综上,我们得到的是一个时间效率和空间效率都相对较高的解决方案。下面是具体的代码实现:
from collections import deque
class RecentCounter:
def __init__(self):
self.queue = deque() # 使用队列存储时间戳
def ping(self, t: int) -> int:
self.queue.append(t) # 添加新的时间戳
# 移除不在 [t-3000, t] 范围内的时间戳
while self.queue and self.queue[0] < t - 3000:
self.queue.popleft()
# 返回队列的长度,即最近3000毫秒内的请求数量
return len(self.queue)
# Your RecentCounter object will be instantiated and called as such:
# obj = RecentCounter()
# param_1 = obj.ping(t)