Ответ
Для проверки строки на палиндром в Python существует два основных подхода: простой с использованием среза и более эффективный с двумя указателями.
1. Простой и "Pythonic" способ (срез)
Этот метод наиболее читаем и краток. Он идеально подходит для большинства случаев.
Логика:
- Строка нормализуется: удаляются все небуквенно-цифровые символы и она приводится к нижнему регистру.
- Нормализованная строка сравнивается со своей перевернутой копией, полученной с помощью среза
[::-1].
def is_palindrome_slice(s: str) -> bool:
# Оставляем только буквы и цифры, приводим к нижнему регистру
normalized_s = ''.join(char.lower() for char in s if char.isalnum())
# Сравниваем строку с её перевернутой версией
return normalized_s == normalized_s[::-1]
# Пример
print(is_palindrome_slice("A man, a plan, a canal: Panama")) # True
print(is_palindrome_slice("race a car")) # False
2. Эффективный способ (два указателя)
Этот подход более производителен для очень длинных строк, так как не создает в памяти новую перевернутую строку (пространственная сложность O(1) против O(N) у среза).
Логика:
- Два указателя (
left,right) устанавливаются в начало и конец строки. - Указатели движутся навстречу друг другу, сравнивая символы. Если символы не совпадают, строка не является палиндромом.
- Пробелы и знаки препинания пропускаются.
def is_palindrome_pointers(s: str) -> bool:
left, right = 0, len(s) - 1
while left < right:
# Пропускаем небуквенно-цифровые символы слева
while left < right and not s[left].isalnum():
left += 1
# Пропускаем небуквенно-цифровые символы справа
while left < right and not s[right].isalnum():
right -= 1
if s[left].lower() != s[right].lower():
return False
left += 1
right -= 1
return True
# Пример
print(is_palindrome_pointers("A man, a plan, a canal: Panama")) # True Ответ 18+ 🔞
О, смотри-ка, классическая задачка на палиндром! Ну, это когда слово или фраза читается одинаково с обеих сторон, как «казак» или «А роза упала на лапу Азора». Хотя последнее — это уже пиздец какой-то, блядь, кто это вообще придумал? Ну ладно.
Так вот, есть два основных подхода, как это проверить на Python. Один — для ленивых и умных, второй — для тех, кто хочет показать, что он не просто так сидит, а думает о производительности, блядь.
Первый способ — питонический, в одну строку, почти как магия
Тут всё просто: берём строку, выкидываем из неё всю хуйню вроде пробелов и запятых, приводим к нижнему регистру, а потом сравниваем с её же перевёрнутой копией. Как? Да с помощью среза [::-1], ёпта! Это ж гениально.
def is_palindrome_slice(s: str) -> bool:
# Оставляем только буквы и цифры, приводим к нижнему регистру
normalized_s = ''.join(char.lower() for char in s if char.isalnum())
# Сравниваем строку с её перевернутой версией
return normalized_s == normalized_s[::-1]
# Пример
print(is_palindrome_slice("A man, a plan, a canal: Panama")) # True
print(is_palindrome_slice("race a car")) # False
Работает? Работает. Красиво? Красиво. Но если строка будет размером с «Войну и мир», то создание её перевёрнутой копии в памяти — это уже овердохуища трат. Ну, не то чтобы прям трат, но можно и лучше.
Второй способ — для перфекционистов, которые любят указатели
Тут мы не создаём лишних строк, а бегаем по исходной с двумя указателями — один с начала, другой с конца. И сравниваем символы, пока они не встретятся. Если нашли несовпадение — всё, пиздец, не палиндром.
def is_palindrome_pointers(s: str) -> bool:
left, right = 0, len(s) - 1
while left < right:
# Пропускаем небуквенно-цифровые символы слева
while left < right and not s[left].isalnum():
left += 1
# Пропускаем небуквенно-цифровые символы справа
while left < right and not s[right].isalnum():
right -= 1
if s[left].lower() != s[right].lower():
return False
left += 1
right -= 1
return True
# Пример
print(is_palindrome_pointers("A man, a plan, a canal: Panama")) # True
Вот так вот. Первый способ — для повседневного использования, когда не нужно париться. Второй — если вдруг придётся проверять на палиндром всю Википедию, блядь. Выбирай, что душе угодно.