Задачи на Python: обучение через практику
Задача на Python: проверка строки на палиндром
Палиндромом называют строку, которая читается одинаково в обоих направлениях (например, “radar” или “шалаш”). Самое эффективное решение в Python использует срез для обращения строки. Этот метод работает за O(n) и требует минимального объёма кода.
def is_palindrome(s):
return s == s[::-1]Python programming tasks (задачи по программированию на python)
print(is_palindrome("radar")) # True
print(is_palindrome("hello")) # Falseзадачи на python c решением (задачи на python с решением)
Типичные ошибки. Забывают о регистре: “Radar” вернёт False, хотя по смыслу это палиндром. Перед проверкой следует приводить строку к одному регистру. Также срез создаёт копию строки, что при очень больших объёмах данных может увеличить потребление памяти.
Как проверить палиндром без использования встроенного обращения?
Можно организовать цикл, сравнивая символы с обоих концов строки. Этот способ более нагляден для новичков и не требует дополнительной памяти для обратной копии.
def is_palindrome_loop(s):
left, right = 0, len(s) - 1
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True
print(is_palindrome_loop("level")) # True
print(is_palindrome_loop("test")) # False
Частые проблемы. Пропуск обновления указателя right приводит к бесконечному циклу. Необходимо учитывать пустые строки или строки из одного символа – функция корректно вернёт True. Цикл работает медленнее среза из-за накладных расходов на выполнение Python-операций, но для большинства задач разница незаметна.
Как игнорировать пробелы, знаки препинания и регистр при проверке палиндрома?
Реальные строки часто содержат пробелы, заглавные буквы и символы пунктуации. Для корректной проверки необходимо очистить строку от лишних символов и привести всё к нижнему регистру.
import re
def is_palindrome_cleaned(s):
cleaned = re.sub(r'[^a-zA-Zа-яА-ЯёЁ0-9]', '', s).lower()
return cleaned == cleaned[::-1]
print(is_palindrome_cleaned("A man, a plan, a canal: Panama")) # True
print(is_palindrome_cleaned("Was it a car or a cat I saw?")) # True
print(is_palindrome_cleaned("Hello, World!")) # False
Возможные затруднения. Регулярное выражение может быть избыточным для простых случаев. Если требуется учитывать только буквы, можно использовать строковый метод isalpha() в фильтре. При работе с многобайтовыми кодировками (например, с эмодзи) регулярное выражение требует доработки. Использование модуля re замедляет выполнение на больших текстах.
Как реализовать проверку палиндрома рекурсивно?
Рекурсивный подход хорошо демонстрирует идею “разделяй и властвуй”, но для длинных строк может привести к переполнению стека вызовов.
def is_palindrome_rec(s):
if len(s) <= 1:
return True
if s[0] != s[-1]:
return False
return is_palindrome_rec(s[1:-1])
print(is_palindrome_rec("racecar")) # True
print(is_palindrome_rec("python")) # False
Ограничения рекурсии. По умолчанию глубина рекурсии в Python ограничена 1000 вызовами. Для строк длиннее 1000 симвонов функция приведёт к ошибке RecursionError. Этот способ подходит только для обучения или заведомо коротких строк. Для производственного кода лучше использовать итеративные решения.
Расширенные примеры работы с палиндромами
1. Проверка палиндрома для целых чисел
Числа также могут быть палиндромами, например, 121 или 12321. Решение строится на обратном формировании числа.
def is_palindrome_number(x):
if x < 0:
return False
original = x
reversed_num = 0
while x > 0:
digit = x % 10
reversed_num = reversed_num * 10 + digit
x //= 10
return original == reversed_num
print(is_palindrome_number(121)) # True print(is_palindrome_number(-121)) # False (отрицательные числа не считаются) print(is_palindrome_number(10)) # False
2. Поиск всех палиндромов в тексте
Задача найти все слова или подстроки, являющиеся палиндромами, в заданном тексте. Следующий код выделяет слова длиннее одного символа.
import re
def find_palindromes(text):
words = re.findall(r'\b\w+\b', text)
palindromes = []
for word in words:
if word.lower() == word.lower()[::-1] and len(word) > 1:
palindromes.append(word)
return palindromes
text = "level radar hello madam world"
print(find_palindromes(text)) # ['level', 'radar', 'madam']
['level', 'radar', 'madam']
3. Палиндром с использованием двусторонней очереди (collections.deque)
Модуль collections предоставляет структуру данных deque, которая позволяет эффективно извлекать элементы с обоих концов.
from collections import deque
def is_palindrome_deque(s):
dq = deque(s)
while len(dq) > 1:
if dq.popleft() != dq.pop():
return False
return True
print(is_palindrome_deque("racecar")) # True
print(is_palindrome_deque("python")) # False
True False
4. Проверка палиндрома с учётом юникода (эмодзи, кириллица)
Регулярное выражение для удаления всего, кроме букв, должно корректно обрабатывать любые алфавиты. Пример для русского и английского.
import re
def is_palindrome_unicode(s):
# Удалить всё, кроме букв и цифр любых языков
cleaned = re.sub(r'[^\w]', '', s, flags=re.UNICODE).lower()
return cleaned == cleaned[::-1]
print(is_palindrome_unicode("А роза упала на лапу Азора")) # True
print(is_palindrome_unicode("???")) # True (эмодзи тоже 'буквы' с точки зрения \w)
True True