Назад к материалам

Видео + статья / Собеседования

Python на собеседовании: сложность операций, изменяемость и задача на массив

Разбираем частые вопросы Python-секции: сложность списков и словарей, изменяемые значения по умолчанию, сортировку и перенос нулей за один проход.

Компания
Газпромбанк
Опубликовано
Обновлено
Видео вышло
Видео
10:52
Текст
5 минут

Если ролик не загружается, выберите другую площадку.

Смотреть на

Это техническая 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 — именованные в словарь.

Те же символы распаковывают коллекции при вызове. Это полезно в обёртках и декораторах, но не заменяет понятную сигнатуру. Если функция принимает строго известные данные, лучше назвать параметры явно.

Пример кодаPython
def show_request(*args, **kwargs):
    # args — кортеж позиционных значений.
    print(args)
    # kwargs — словарь именованных значений.
    print(kwargs)

show_request("users", limit=10)

Как отсортировать 32 ГБ данных при 1 ГБ памяти

Короткий ответ: применить внешнюю сортировку слиянием.

Файл читают частями, которые помещаются в доступную память. Каждую часть сортируют и записывают во временный файл. Затем открывают отсортированные части как потоки и сливают их, каждый раз выбирая минимальный текущий элемент.

Размер части должен учитывать не только исходные данные, но и накладные расходы объектов, буферы и работу сортировки. Поэтому нельзя просто объявить блок ровно в 1 ГБ.

Такой ответ показывает главное: мы соблюдаем ограничение памяти и не пытаемся загрузить весь набор одновременно.

Почему опасен список в аргументе по умолчанию

Короткий ответ: значение по умолчанию вычисляется один раз при создании функции, а не при каждом вызове.

Пример кодаPython
def add_item(item, items=None):
    # Новый список создаём для конкретного вызова.
    if items is None:
        items = []

    # Переданный пользователем список по-прежнему можно изменять явно.
    items.append(item)
    return items

Если написать items=[] прямо в сигнатуре, один объект будет жить между вызовами. Первый вызов добавит элемент, а второй увидит уже изменённый список. Это не ошибка языка, а следствие модели объектов Python.

Можно ли изменить объект внутри кортежа

Короткий ответ: да, если сам вложенный объект изменяемый.

Кортеж запрещает заменить одну ссылку другой: нельзя присвоить новое значение по индексу. Но он не делает вложенный список неизменяемым. Такой список всё ещё можно дополнить.

Из-за этого кортеж с изменяемым объектом обычно нельзя использовать как ключ словаря: его содержимое не образует стабильное хешируемое значение. На интервью полезно разделять неизменяемость контейнера и объектов, на которые он ссылается.

Как перенести нули в конец списка

Короткий ответ: хранить позицию следующего ненулевого элемента и пройти список один раз.

Пример кода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)?

Храните позицию для следующего ненулевого элемента. Проходите по списку один раз и меняйте местами найденный ненулевой элемент с элементом на сохранённой позиции.

следующий шаг

Потренируйте Python-секцию до собеседования

В тренажёре ЮНИКОД можно пройти вопросы по Python, заметить слабые темы и закрепить структуру ответа.

Перейти к вопросам →