Как логически проверить, что число является палиндромом, работая с самим числом?
Что проверяют
Умеете ли вы работать с цифрами числа арифметикой, без перевода в строку, и видите ли граничные случаи. Решение через str(x)[::-1] интервьюер знает и попросит обойтись без него, а следом спросит про сложность и отрицательные числа.
Как отвечать
Идея: отделять цифры с конца через % 10 и // 10 и собирать из них перевёрнутое число. Переворачивать всё число не нужно, хватит половины:
def is_palindrome(x: int) -> bool:
if x < 0 or (x % 10 == 0 and x != 0):
return False
rev = 0
while x > rev:
rev = rev * 10 + x % 10
x //= 10
return x == rev or x == rev // 10Что стоит проговорить:
- отрицательные числа: минус стоит только слева, поэтому они не палиндромы. Проверять это надо первым делом ещё и потому, что в Python
-121 % 10равно9: деление округляется вниз, и цикл выдал бы ерунду; - нули в конце: число вида
10или120не начинается с нуля, значит палиндромом быть не может; - нечётная длина: для
12321цикл остановится наx = 12иrev = 123. Средняя цифра на ответ не влияет, её отбрасывают черезrev // 10; - сложность: O(d) по времени, где d число цифр, то есть O(log n), и O(1) памяти.
Почему половина: в языках с фиксированной разрядностью полный переворот большого числа переполняет int. В Python целые не переполняются, так что полный переворот с копией исходного числа тоже корректен, но половина короче и показывает, что вы знаете классическое решение.
Где спотыкаются
Всё равно переводят в строку или в список цифр. Условие «работая с самим числом» как раз это исключает.
Забывают про нули в конце и получают True для 10: цикл заканчивается с rev = 1 и x = 0, и срабатывает x == rev // 10.
Портят входное значение и потом сравнивают с ним же. Если переворачиваете целиком, сохраните копию до цикла.