Программа курса:
Разбор задачи: Количество недавних звонков
Предложенный нами код решения:
from collections import deque
class RecentCounter(object):
def __init__(self):
"""
Инициализация:
- Задайте структуру данных для хранения временных меток запросов.
"""
# Используем deque для эффективной работы с очередью
self.queue = deque()
def ping(self, t):
"""
Добавляет запрос с меткой времени t и возвращает количество запросов за последние 3000 миллисекунд.
:type t: int
:rtype: int
"""
# Добавляем метку времени в очередь
self.queue.append(t)
# Удаляем старые запросы, которые находятся за пределами временного интервала [t - 3000, t]
while self.queue[0] < t - 3000:
self.queue.popleft() # Удаляем элементы с начала очереди
# Возвращаем количество оставшихся запросов
return len(self.queue)
Задача заключается в том, чтобы реализовать класс RecentCounter, который отслеживает количество запросов, сделанных за последние 3000 миллисекунд. Каждый запрос имеет свою метку времени t, и нам нужно вернуть количество запросов, сделанных за период времени от t-3000 до t (включая текущий запрос).
1. Инициализация класса (__init__)
В конструкторе класса создается структура данных для хранения временных меток запросов. В данном случае используется очередь deque из библиотеки collections.
Почему deque?
Очередь, реализованная через deque, удобна тем, что позволяет эффективно добавлять элементы в конец и удалять элементы с начала. Это важно, потому что нам нужно поддерживать в очереди только те запросы, которые попадают в временной интервал от t-3000 до t.
self.queue = deque()
2. Метод ping
Метод ping принимает метку времени запроса и добавляет её в очередь. Затем происходит очистка очереди от старых запросов, метки времени которых меньше, чем t - 3000, чтобы оставить в очереди только те запросы, которые попадают в интервал [t-3000, t].
Шаги работы метода ping:
Добавление текущего запроса в очередь: Каждый раз, когда вызывается метод
ping, метка времени запросаtдобавляется в конец очереди.self.queue.append(t)Удаление старых запросов из очереди: После добавления нового запроса необходимо удалить все старые запросы, которые не попадают в нужный временной интервал. Для этого из очереди удаляются элементы с начала, пока первый элемент очереди не станет таким, что его метка времени лежит в интервале [t-3000, t].
while self.queue[0] < t - 3000: self.queue.popleft()Возврат количества запросов, попадающих в интервал: После того как старые запросы удалены, в очереди остаются только те, которые находятся в интервале [t-3000, t]. Количество таких запросов возвращается в виде длины очереди.
return len(self.queue)
Пример работы:
- При первом вызове
ping(1)в очереди будет только один запрос (метка времени1), и метод вернет1. - При вызове
ping(100)в очереди будет два запроса:1и100, и метод вернет2, так как оба запроса попадают в интервал [100-3000, 100]. - При вызове
ping(3001)в очереди будут три запроса:1,100и3001. Интервал теперь будет [3001-3000, 3001], и метод вернет3.
Почему решение работает корректно?
- Очередь: Используя
deque, мы эффективно управляем добавлением и удалением запросов. Запросы добавляются в конец очереди, а старые запросы удаляются с начала очереди. Это оптимизирует процесс подсчета актуальных запросов в интервале. - Простота: Каждая метка времени добавляется в очередь, а затем удаляются только те метки, которые не попадают в интервал, что делает решение простым и понятным.
Решение хорошо работает в условиях задачи, поскольку все операции по добавлению и удалению элементов происходят в предсказуемое время и без сложных вычислений.