Это техническая Python-секция собеседования в Газпромбанке. Точная позиция и грейд не названы, но набор вопросов подходит Data Scientist или Python-разработчику с уверенной базой. Здесь проверяют сложность коллекций, функции, память и алгоритмическое мышление.
Какая сложность операций со списком и словарём
Короткий ответ: доступ к элементу списка по индексу — O(1), поиск значения — O(n), доступ к словарю по ключу в среднем — O(1).
Список хранит ссылки на элементы подряд, поэтому адрес позиции вычисляется напрямую. Но для поиска значения приходится сравнивать элементы по очереди. Вставка в начало также занимает O(n), потому что остальные ссылки нужно сдвинуть.
Словарь использует хеш-таблицу. По хешу ключа Python находит нужную область, а затем проверяет совпадение. В среднем это быстро, но корректный ответ должен содержать слова «в среднем»: при неудачных коллизиях работа может стать дороже.

Чем выше кривая, тем быстрее растёт время работы при увеличении входа; таблицу используют как ориентир, а не вместо анализа конкретного кода. Источник: Eric Rowell, Wikimedia Commons, общественное достояние.
Типичная ошибка. Называть одну сложность без операции, структуры и условий. Фраза «словарь работает за O(1)» звучит как заученная и не учитывает построение словаря, перебор или худший случай.
Как лучше. Отвечайте в формате «операция → средний случай → важное исключение». Например: доступ по ключу в словаре в среднем занимает O(1), но перебор всех элементов — O(n).
Что делают args и kwargs
Короткий ответ: *args собирает лишние позиционные аргументы в кортеж, а **kwargs — именованные в словарь.
Те же символы распаковывают коллекции при вызове. Это полезно в обёртках и декораторах, но не заменяет понятную сигнатуру. Если функция принимает строго известные данные, лучше назвать параметры явно.
def show_request(*args, **kwargs):
# args — кортеж позиционных значений.
print(args)
# kwargs — словарь именованных значений.
print(kwargs)
show_request("users", limit=10)Как отсортировать 32 ГБ данных при 1 ГБ памяти
Короткий ответ: применить внешнюю сортировку слиянием.
Файл читают частями, которые помещаются в доступную память. Каждую часть сортируют и записывают во временный файл. Затем открывают отсортированные части как потоки и сливают их, каждый раз выбирая минимальный текущий элемент.
Размер части должен учитывать не только исходные данные, но и накладные расходы объектов, буферы и работу сортировки. Поэтому нельзя просто объявить блок ровно в 1 ГБ.
Такой ответ показывает главное: мы соблюдаем ограничение памяти и не пытаемся загрузить весь набор одновременно.
Почему опасен список в аргументе по умолчанию
Короткий ответ: значение по умолчанию вычисляется один раз при создании функции, а не при каждом вызове.
def add_item(item, items=None):
# Новый список создаём для конкретного вызова.
if items is None:
items = []
# Переданный пользователем список по-прежнему можно изменять явно.
items.append(item)
return itemsЕсли написать items=[] прямо в сигнатуре, один объект будет жить между вызовами. Первый вызов добавит элемент, а второй увидит уже изменённый список. Это не ошибка языка, а следствие модели объектов Python.
Можно ли изменить объект внутри кортежа
Короткий ответ: да, если сам вложенный объект изменяемый.
Кортеж запрещает заменить одну ссылку другой: нельзя присвоить новое значение по индексу. Но он не делает вложенный список неизменяемым. Такой список всё ещё можно дополнить.
Из-за этого кортеж с изменяемым объектом обычно нельзя использовать как ключ словаря: его содержимое не образует стабильное хешируемое значение. На интервью полезно разделять неизменяемость контейнера и объектов, на которые он ссылается.
Как перенести нули в конец списка
Короткий ответ: хранить позицию следующего ненулевого элемента и пройти список один раз.
def move_zeroes(numbers):
# Сюда поставим следующий ненулевой элемент.
write = 0
for read in range(len(numbers)):
# Ноль пока пропускаем, остальные значения двигаем влево.
if numbers[read] != 0:
numbers[write], numbers[read] = numbers[read], numbers[write]
write += 1
# Список изменён на месте, дополнительный массив не нужен.
return numbersИнвариант простой: до позиции write уже стоят все встреченные ненулевые элементы в исходном порядке. Время — O(n), дополнительная память — O(1). После решения стоит проверить пустой список, одни нули, отсутствие нулей и чередование значений.
Получил бы кандидат оффер
Короткий ответ: скорее да, по этой секции кандидат прошёл.
Он уверенно отвечал на вопросы, исправлял детали и решил алгоритмическую задачу. Интервьюер завершил секцию положительно. Единственная заметная неточность касалась размера частей во внешней сортировке, но общий подход был верным.
Подобные вопросы можно отработать в тренажёре собеседований ЮНИКОД, чтобы объяснять решение вслух, а не только писать рабочий код.
Источники
частые вопросы
Короткие ответы
Какая сложность поиска элемента в списке Python?
Обычный поиск значения в списке требует в худшем случае просмотреть все элементы, поэтому занимает O(n). Доступ по известному индексу обычно занимает O(1).
Почему нельзя ставить пустой список значением аргумента по умолчанию?
Значение по умолчанию вычисляется один раз при создании функции. Один и тот же список будет использоваться в следующих вызовах и сохранит ранее добавленные элементы.
Как перенести все нули в конец списка за O(n)?
Храните позицию для следующего ненулевого элемента. Проходите по списку один раз и меняйте местами найденный ненулевой элемент с элементом на сохранённой позиции.


