Как сопоставить каждую букву шаблона с одним словом из строки?
Что проверяют
Это задача о биекции: каждой букве соответствует ровно одно слово, и каждому слову ровно одна буква. Проверяют, заметите ли вы вторую половину условия и не забудете ли про длины. Следом обычно спрашивают сложность и просят решение короче.
Как отвечать
Сначала проговорите условие на примерах: "abba" и "dog cat cat dog" дают True, а "abba" и "dog dog dog dog" дают False, потому что a и b отобразились в одно слово. Затем алгоритм:
- разбить строку:
s.split()без аргумента режет по любым пробельным символам и выбрасывает пустые куски, в отличие отsplit(" "); - сравнить длины: при разном числе букв и слов сразу
False. Без проверкиzipмолча обрежет длинную последовательность; с Python 3.10 можно писатьzip(pattern, words, strict=True), и он броситValueError; - два словаря: из букв в слова и из слов в буквы. На каждой паре сохранённое соответствие должно совпасть с текущим.
def word_pattern(pattern: str, s: str) -> bool:
words = s.split()
if len(pattern) != len(words):
return False
char_to_word, word_to_char = {}, {}
for ch, w in zip(pattern, words):
if char_to_word.setdefault(ch, w) != w:
return False
if word_to_char.setdefault(w, ch) != ch:
return False
return TrueСложность O(n) по времени и памяти, где n это длина строки: доступ к словарю в среднем O(1).
Короткий вариант при равных длинах: len(set(pattern)) == len(set(words)) == len(set(zip(pattern, words))). На собеседовании его нужно объяснить: число уникальных пар совпадает с числом уникальных букв и слов только при взаимно однозначном соответствии.
Где спотыкаются
Заводят один словарь из букв в слова. Тогда "abba" и "dog dog dog dog" проходят проверку, хотя должны давать False.
Не сравнивают длины и получают True на "aaa" и "dog dog dog dog": zip остановится на коротком.
Ищут соответствие через list.index внутри цикла. Код работает, но каждый поиск линейный, выходит O(n²), и интервьюер это обязательно заметит.