Вступить в клуб →
сложнаявопросСложность и стоимость структур данных

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

Два способа собрать строку из n кусков:

# A
def build_a(parts):
    s = ""
    for p in parts:
        s += p
    return s

# B
def build_b(parts):
    return "".join(parts)

На списке из 300 000 коротких строк вариант A иногда работает почти линейно, а иногда — катастрофически медленно (например, если в цикле результат ещё куда-то сохраняется: acc.append(s)). Какое объяснение верно?

  • Разницы по сложности нет: `join` — тот же цикл конкатенации, просто написанный на C, поэтому отличается только константа, а порядок роста одинаков
  • Строки неизменяемы: `s += p` копирует весь накопленный результат, поэтому A в общем случае квадратичен, а B копирует каждый кусок ровно один раз; линейность A держится на необязательной оптимизации CPython
  • A всегда быстрее B на коротких кусках: `join` сначала обходит весь список ради подсчёта суммарной длины, и этот лишний проход дороже самой конкатенации
  • A медленнее из-за сборщика мусора: промежуточные строки копятся до конца цикла и освобождаются разом, из-за чего пик памяти растёт и запускается сборка

🔒 Проверка ответа — для участников клуба

  • Проверка ответа
  • Подсказка, если застряли
  • Разбор с объяснением, почему так
  • Прогресс по всем задачам и виртуальные собеседования
Зарегистрироваться →

Регистрация занимает минуту

Другие задачи раздела