Задачи по Python с собеседований
Python·junior

Проверь, что две строки — анаграммы

Задачу на анаграммы дают на скрининге, чтобы посмотреть, как ты работаешь со строками и знаешь ли идиоматичные приёмы Python. Решается в одну строку, но за этой строкой прячется мысль про нормализацию и подсчёт символов — а её как раз и просят проговорить.

Задача

Две строки — анаграммы, если состоят из одних и тех же букв в одинаковом количестве, просто переставленных. Регистр не важен: «Лунь» и «нуль» — анаграммы.

Напиши функцию is_anagram(s1, s2), которая возвращает True, если строки — анаграммы, и False иначе. Проверь на парах: золотарник/разнотолки, Лунь/нуль, Воз/зов, песнь/снедь.

Решение

from collections import Counter


def is_anagram(s1, s2):
    return sorted(s1.lower()) == sorted(s2.lower())


def is_anagram_counter(s1, s2):
    return Counter(s1.lower()) == Counter(s2.lower())


cases = [
    ("золотарник", "разнотолки"),
    ("Лунь", "нуль"),
    ("Воз", "зов"),
    ("песнь", "снедь"),
]
for a, b in cases:
    r1 = is_anagram(a, b)
    r2 = is_anagram_counter(a, b)
    print(f"{a!r} и {b!r} -> {r1} (Counter: {r2})")

Разбор

Идея решения простая: если два слова состоят из одинакового набора букв, то после сортировки символов они превратятся в одну и ту же последовательность. sorted('лунь') и sorted('нуль') дают идентичный список букв — значит, анаграммы.

Два обязательных шага, которые легко забыть. Первый — нормализация регистра через .lower(). Без неё «Лунь» и «нуль» не совпадут: заглавная Л и строчная н — разные символы. Собеседующий специально подсовывает пару с разным регистром, чтобы проверить, заметишь ли ты это. Второй — сравнение именно отсортированных последовательностей, а не строк напрямую.

Пара песнь/снедь — контрпример: буквы почти те же, но набор различается (в одном слове п и мягкий знак, в другом д и е), поэтому отсортированные списки не совпадают и функция честно возвращает False. Важно, что решение проверяет не только состав, но и количество каждой буквы: два а в одном слове и одно а в другом дадут разные отсортированные списки.

Альтернатива — collections.Counter. Он строит словарь «буква → сколько раз встретилась», и два таких словаря сравниваются напрямую. По сути та же идея — сравнить состав, — но Counter работает за линейное время O(n), тогда как sorted — за O(n log n). На словах из десятка букв разницы никакой, а на длинных строках Counter предпочтительнее; к тому же он нагляднее выражает намерение «посчитать символы». Хороший ответ на собеседовании — назвать оба подхода и объяснить, почему Counter асимптотически быстрее.

Ещё один способ сжать строку в её «подпись» — RLE-кодирование: другая задача на посимвольный проход, где тоже нужно аккуратно считать повторы.

Ожидаемый результат

'золотарник' и 'разнотолки' -> True (Counter: True)
'Лунь' и 'нуль' -> True (Counter: True)
'Воз' и 'зов' -> True (Counter: True)
'песнь' и 'снедь' -> False (Counter: False)

Хочешь так же уверенно решать на собеседовании?

Читать разбор полезно, а настоящая прокачка — самому решать такие задачи и получать обратную связь. Потренируйся в симуляторе аналитика, лёгкий режим — бесплатно.

Прорешать в бесплатной песочнице

Смежные задачи

Вопросы по теме

Из блога