Как упростить функцию проверки наличия подряд идущих единиц с помощью операторов in и not в Python
Что проверяют
Видите ли вы, что ручной цикл с индексами здесь не нужен, и понимаете ли, как оператор in ведёт себя на строках и на списках. Следом часто просят решить ту же задачу для списка чисел или для целого числа в двоичной записи.
Как отвечать
Для строки вся функция сводится к одному выражению:
return '11' in s: для строкinищет подстроку. Поиск реализован на C, это быстрее и читаемее цикла поrange(len(s) - 1)с попарным сравнением;- обратная проверка: «подряд идущих единиц нет» записывается как
'11' not in s. Конструкцияnot '11' in sтоже работает, потому чтоinсвязывает сильнее, чемnot, но PEP 8 рекомендуетnot in; - без
if: выражение уже возвращаетbool, обёрткаif ...: return True else: return Falseлишняя.
Потом покажите, что понимаете границы приёма:
- список:
[1, 1] in lstпроверяет, есть ли в списке элемент, равный списку[1, 1], а не подпоследовательность. Для списка пишутany(a == b == 1 for a, b in zip(lst, lst[1:])), а с Python 3.10 удобнееitertools.pairwise(lst), он не копирует срез; - целое число:
'11' in bin(n)работает, но есть битовый приём без строк:bool(n & (n >> 1)). Сдвиг ставит каждый бит напротив соседа, и ненулевой результат значит, что две единицы стоят рядом; - серия длины k:
'1' * k in sобобщает задачу без смены подхода.
Хорошо добавить пару проверок на краях: пустая строка, строка из одного символа, строка из одних единиц.
Где спотыкаются
Переносят приём со строк на списки и пишут [1, 1] in lst. Получают False на списке [0, 1, 1] и не понимают почему.
Тянут регулярное выражение re.search(r'1{2}', s) туда, где хватает in. Код становится длиннее и медленнее, а интервьюер просил как раз упростить.
Не уточняют формат входа: строка, список или число, и что делать с отрицательными. bin(-3) возвращает '-0b11', а битовый приём на отрицательном числе в Python всегда даёт True, потому что у него бесконечная цепочка единиц в старших разрядах.