Собесов

Магнит Python — длина наибольшей последовательности одинаковых символов

PythonАлгоритмы и строкиЛёгкаяJunior

Условие

Определить длину наибольшей последовательности одинаковых подряд символов в строке.

str = 'fffggggrrrrrrrrrtttfffff'
ответ: 9   # 'rrrrrrrrr'

Решение

Подход 1 — itertools.groupby (самый идиоматичный)

from itertools import groupby
 
def longest_run(s: str) -> int:
    if not s:
        return 0
    return max(sum(1 for _ in g) for _, g in groupby(s))
 
print(longest_run('fffggggrrrrrrrrrtttfffff'))  # 9

groupby группирует подряд идущие одинаковые элементы; для каждой группы считаем длину.

Подход 2 — однопроходный

def longest_run(s: str) -> int:
    if not s:
        return 0
    best = cur = 1
    for i in range(1, len(s)):
        if s[i] == s[i - 1]:
            cur += 1
            best = max(best, cur)
        else:
            cur = 1
    return best

O(n) по времени, O(1) по памяти.

Подход 3 — regex

import re
 
def longest_run(s: str) -> int:
    if not s:
        return 0
    return max((len(m.group()) for m in re.finditer(r'(.)\1*', s)), default=0)

(.)\1* — символ и его повторы. На очень длинных строках регексп медленнее однопроходного.

Тесты

assert longest_run('fffggggrrrrrrrrrtttfffff') == 9
assert longest_run('') == 0
assert longest_run('a') == 1
assert longest_run('abcde') == 1
assert longest_run('aabbbccccdddd') == 4   # 'cccc' и 'dddd' оба по 4

Подводные камни

  1. Пустая строка. Не забыть отдельный случай — иначе max на пустом итерабле падает.
  2. groupby без сортировки. В отличие от SQL GROUP BY, itertools.groupby группирует подряд идущие, без сортировки. Это и нужно — порядок важен.
  3. Юникод и комбинируемые символы. В строке 'á' (где á — 'a' + combining acute) формально две кодовые точки, но визуально один символ. Если задача про graphemes — нужен unicodedata или regex с \X.
  4. Регистр. 'Aaaa' — это 4 одинаковых или 1+3? Уточнить у бизнеса; обычно — case-sensitive.
  5. Сравнение позиций. В цикле range(1, len(s)) важно начинать с 1, иначе s[i-1] упадёт на индексе −1.

Эталонный ответ

from itertools import groupby
def longest_run(s):
    return max((sum(1 for _ in g) for _, g in groupby(s)), default=0)

groupby группирует подряд одинаковые → длина каждой группы → max. Алгоритмически — O(n).

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти