Python тестовое задание: как успешно решить задачу на палиндром

Раздел: Обучение Python -> Подготовка к экзаменам

Разбор типового тестового задания: проверка строки на палиндром

Наиболее эффективное решение

Для проверки, является ли строка палиндромом, оптимально использовать сравнение с обратной версией строки после нормализации. Этот подход имеет сложность O(n) по времени и O(n) по памяти (на создание обратной строки).

def is_palindrome(s: str) -> bool:
    """Проверяет, является ли строка палиндромом (без учёта регистра)."""
    # Нормализация: приводим к нижнему регистру
    normalized = s.lower()
    # Сравниваем с обратной строкой
    return normalized == normalized[::-1]

яндекс задания python (задания от яндекса по python)

# Пример использования
print(is_palindrome("Racecar"))  # True
print(is_palindrome("Python"))   # False

Python разработчик тестовые задания (примеры тестовых заданий python)

Пояснение: метод [::-1] создаёт срез с шагом -1, что даёт строку в обратном порядке. Сравнение выполняется поэлементно. Нормализация через lower() позволяет игнорировать регистр.

Как проверить палиндром без использования срезов?

Если по условию запрещено использовать срезы или требуется показать понимание алгоритма, можно применить цикл с двумя указателями.

def is_palindrome_two_pointers(s: str) -> bool:
    """Проверка двумя указателями."""
    left, right = 0, len(s) - 1
    while left < right:
        if s[left].lower() != s[right].lower():
            return False
        left += 1
        right -= 1
    return True

егэ python задачи (задачи егэ по python)

print(is_palindrome_two_pointers("Aba"))  # True
print(is_palindrome_two_pointers("Hello"))  # False

решу егэ python (решение заданий егэ по python)

Проблема: при очень длинных строках цикл может быть медленным, но это незначительно. Типичная ошибка: забыть про приведение к нижнему регистру.

Как реализовать рекурсивную проверку палиндрома?

Рекурсивный подход нагляден, но неэффективен для длинных строк из-за переполнения стека.

def is_palindrome_recursive(s: str) -> bool:
    """Рекурсивная проверка."""
    if len(s) <= 1:
        return True
    if s[0].lower() != s[-1].lower():
        return False
    return is_palindrome_recursive(s[1:-1])

Python тестовое (тестовое задание python)

print(is_palindrome_recursive("Level"))  # True
print(is_palindrome_recursive("Test"))   # False

задачи огэ python (задачи огэ по python)

Проблемы: глубина рекурсии не может превышать лимит (обычно 1000), поэтому для строк длиннее 500 символов возможна ошибка. Решение: использовать итеративный вариант или увеличить лимит через sys.setrecursionlimit.

Как проверить палиндром с учётом пробелов и знаков препинания?

Часто в тестовых заданиях требуется игнорировать все небуквенные символы. Например, фраза "А роза упала на лапу Азора" считается палиндромом.

import re

def is_palindrome_cleaned(s: str) -> bool:
    """Проверка после удаления небуквенных символов."""
    # Оставляем только буквы и цифры (можно и только буквы)
    cleaned = re.sub(r'[^a-zA-Zа-яА-Я0-9]', '', s).lower()
    return cleaned == cleaned[::-1]

задачи python 9 класс (задачи по python для 9 класса)

print(is_palindrome_cleaned("A man, a plan, a canal: Panama"))  # True
print(is_palindrome_cleaned("А роза упала на лапу Азора"))       # True

олимпиады python задачи (олимпиадные задачи по python)

Проблема: регулярное выражение создаёт дополнительную строку и может быть медленным на больших текстах. Альтернатива: использовать filter(str.isalnum, s) или вручную проверять каждый символ.

Как проверить палиндром без дополнительной памяти?

Если требуется константная память O(1), можно использовать два указателя, пропуская небуквенные символы на ходу.

def is_palindrome_inplace(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

егэ информатика 19 задание python (19 задание егэ по информатике на python)

print(is_palindrome_inplace("Was it a car or a cat I saw?"))  # True
print(is_palindrome_inplace("No 'x' in Nixon."))                 # True

Проблема: нужно аккуратно управлять указателями, чтобы не выйти за границы. Типичная ошибка: бесконечный цикл, если все символы небуквенные (но условие left < right остановит).

Типичные проблемы и способы их решения

  • Проблема: Не учитывается регистр. Решение: Обязательно приводить строку к одному регистру (lower() или casefold() для лучшей обработки Unicode).
  • Проблема: Пустая строка или строка из одного символа. Решение: Такие строки являются палиндромами по определению - алгоритмы должны возвращать True.
  • Проблема: Строка содержит символы Unicode (например, эмодзи, акценты). Решение: Использовать casefold() вместо lower() и unicodedata.normalize() для приведения к общему виду.
  • Проблема: Переполнение стека при рекурсии для длинных строк. Решение: Выбирать итеративные алгоритмы.
  • Проблема: Некорректное удаление пробелов и знаков препинания (например, апострофы или дефисы). Решение: Определить чёткий список символов, которые считаются значимыми (цифры, буквы).

Расширенные примеры и углублённые техники

Пример 1. Проверка палиндрома с обработкой Unicode (французские акценты)

Пример
import unicodedata

def is_palindrome_unicode(s: str) -> bool:
    # Удаляем диакритические знаки
    nfkd = unicodedata.normalize('NFKD', s)
    ascii_str = nfkd.encode('ASCII', 'ignore').decode('ASCII')
    cleaned = ''.join(filter(str.isalnum, ascii_str)).lower()
    return cleaned == cleaned[::-1]

print(is_palindrome_unicode("Élevé"))  # False, так как "elev" не палиндром
print(is_palindrome_unicode("Racecar"))  # True
False
True

Пример 2. Проверка палиндрома для чисел (задача из LeetCode)

Пример
def is_palindrome_number(x: int) -> bool:
    # Отрицательные числа не могут быть палиндромами
    if x < 0 or (x % 10 == 0 and x != 0):
        return False
    reversed_half = 0
    while x > reversed_half:
        reversed_half = reversed_half * 10 + x % 10
        x //= 10
    # Для чётного и нечётного количества цифр
    return x == reversed_half or x == reversed_half // 10

print(is_palindrome_number(121))   # True
print(is_palindrome_number(-121))  # False
print(is_palindrome_number(10))    # False
True
False
False

Пример 3. Палиндром с использованием стека

Пример
def is_palindrome_stack(s: str) -> bool:
    stack = []
    # помещаем первую половину символов в стек
    length = len(s)
    for i in range(length // 2):
        stack.append(s[i].lower())
    # сравниваем со второй половиной (для нечётной длины пропускаем средний)
    start = length // 2 + (length % 2)
    for i in range(start, length):
        if s[i].lower() != stack.pop():
            return False
    return True

print(is_palindrome_stack("Racecar"))  # True
print(is_palindrome_stack("Python"))   # False
True
False

Пример 4. Сравнение производительности разных методов (timeit)

Пример
import timeit

test_str = "A man, a plan, a canal, Panama!" * 100

time_slice = timeit.timeit(lambda: is_palindrome_cleaned(test_str), number=100)
time_pointers = timeit.timeit(lambda: is_palindrome_inplace(test_str), number=100)

print(f"Срез с regex: {time_slice:.4f} сек")
print(f"Два указателя in-place: {time_pointers:.4f} сек")
Срез с regex: 0.0254 сек
Два указателя in-place: 0.0123 сек

Пример 5. Проверка палиндрома для связного списка (задача для собеседования)

Пример
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def is_palindrome_linked_list(head: ListNode) -> bool:
    # Находим середину списка (метод двух указателей)
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
    # Переворачиваем вторую половину
    prev = None
    while slow:
        nxt = slow.next
        slow.next = prev
        prev = slow
        slow = nxt
    # Сравниваем с первой половиной
    left, right = head, prev
    while right:
        if left.val != right.val:
            return False
        left = left.next
        right = right.next
    return True

# Создаём список [1->2->2->1]
head = ListNode(1, ListNode(2, ListNode(2, ListNode(1))))
print(is_palindrome_linked_list(head))  # True
True

Тестовое задание Python - comments

En
Python тестовое (python)