Разбор типовых упражнений по программированию на Python

Раздел: Обучение Python -> Учебные задачи

Решение задач по программированию на Python - эффективный способ освоить язык. Рассмотрим задачу проверки строки на палиндром и различные подходы к её реализации.

Проверка строки на палиндром

Наиболее эффективное решение - использование среза строки после очистки от незначащих символов.

def is_palindrome(s):
    cleaned = ''.join(c.lower() for c in s if c.isalnum())
    return cleaned == cleaned[::-1]

алгоритм решения задачи python (алгоритм решения задачи на python)

Пояснение: генератор собирает буквы и цифры, приводит их к нижнему регистру, затем сравниваем исходную очищенную строку с её обратной копией (срез [::-1]). Временная сложность O(n), память O(n) для очищенной строки и копии. Подходит для большинства практических случаев.

Типичная ошибка: забыть очистить строку от пробелов и знаков препинания. Например, 'A man, a plan, a canal, Panama' не распознается как палиндром без удаления запятых и пробелов. Решение - использовать isalnum() или isalpha() в комбинации со lower(). Также важно учитывать, что метод создает новую строку; для очень длинных строк может потребоваться оптимизация по памяти.

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

Алгоритм использует два индекса: левый (начало) и правый (конец), двигающиеся навстречу до пересечения. Если на любом шаге символы не совпадают, строка не является палиндромом.

def is_palindrome_two_pointers(s):
    cleaned = ''.join(c.lower() for c in s if c.isalnum())
    left, right = 0, len(cleaned) - 1
    while left < right:
        if cleaned[left] != cleaned[right]:
            return False
        left += 1
        right -= 1
    return True

базовые задачи python (базовые задачи python)

Данный подход не создает копию строки для сравнения, что экономит память (O(1) дополнительно). Однако требует аккуратной работы с индексами и проверки выхода за границы. Используется, когда память критична (например, в embedded-системах).

Ошибка: неверное условие цикла (while left <= right) может привести к двойному сравнению центрального символа для нечетной длины. Правильно - while left < right.

Как проверить палиндром с помощью reversed()?

Функция reversed() возвращает итератор, который обходит последовательность в обратном порядке. Сравнение можно выполнить через преобразование в список.

def is_palindrome_reversed(s):
    cleaned = ''.join(c.lower() for c in s if c.isalnum())
    return list(cleaned) == list(reversed(cleaned))

задачи для обучения python (задачи для обучения python)

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

Ошибка: прямое сравнение cleaned == reversed(cleaned) неверно, так как reversed возвращает итератор, который не равен строке. Необходимо явное преобразование в последовательность.

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

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

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])

задачи на классы в python (задачи на классы в python)

Данный подход иллюстрирует принцип рекурсии, но неэффективен для длинных строк (глубина рекурсии может превысить лимит). Используется в учебных задачах для понимания рекурсии.

Ошибка: вызов функции с очень длинной строкой может вызвать RecursionError. Рекомендуется увеличить лимит рекурсии через sys.setrecursionlimit или использовать итеративный подход.

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

Структура данных deque позволяет эффективно удалять элементы с обоих концов.

from collections import deque

def is_palindrome_deque(s):
    cleaned = ''.join(c.lower() for c in s if c.isalnum())
    dq = deque(cleaned)
    while len(dq) > 1:
        if dq.popleft() != dq.pop():
            return False
    return True

Deque даёт асимптотику O(n) с памятью O(n) (для хранения копии). Этот вариант удобен, когда требуется одновременно обращаться к обоим концам.

Ошибка: метод pop() по умолчанию удаляет с правого конца, а popleft() - с левого. Важно не перепутать порядок. Также при нечетной длине в конце в deque останется один элемент, что корректно.

- задачи на операторы в python (задачи на операторы в python)
- задачи на последовательности python (задачи на последовательности в python)
- задачи на списки python (задачи на списки в python)

Дополнительные примеры и нестандартные подходы

В этом разделе рассматриваются расширенные реализации, которые могут быть полезны в реальных проектах.

Проверка числа на палиндром без преобразования в строку

Математический подход: разворачиваем число, извлекая последние цифры, и сравниваем с оригиналом.

Пример
def is_palindrome_number(n):
    if n < 0 or (n % 10 == 0 and n != 0):
        return False
    reversed_half = 0
    while n > reversed_half:
        reversed_half = reversed_half * 10 + n % 10
        n //= 10
    return n == reversed_half or n == reversed_half // 10
print(is_palindrome_number(12321))  # True
print(is_palindrome_number(12345))  # False

Пояснение: алгоритм разворачивает вторую половину числа и сравнивает с первой половиной. Это эффективно (O(log n)) и не требует преобразования типов.

Ошибка: не учтены отрицательные числа (они не могут быть палиндромами) и числа, заканчивающиеся на ноль (кроме нуля).

Поиск всех подстрок-палиндромов в строке

Метод расширения от центра: для каждой позиции (и промежутка между символами) проверяется, насколько сильно можно расширить палиндром.

Пример
def find_all_palindromic_substrings(s):
    res = set()
    for i in range(len(s)):
        # нечетная длина
        l, r = i, i
        while l >= 0 and r < len(s) and s[l] == s[r]:
            res.add(s[l:r+1])
            l -= 1
            r += 1
        # четная длина
        l, r = i, i+1
        while l >= 0 and r < len(s) and s[l] == s[r]:
            res.add(s[l:r+1])
            l -= 1
            r += 1
    return list(res)
print(find_all_palindromic_substrings('abcbab'))
# ['a', 'b', 'c', 'b', 'a', 'bcb', 'abcba', 'bab']

Пояснение: алгоритм обрабатывает каждый символ как центр потенциального палиндрома. Временная сложность O(n^2), но он находит все подстроки. Используется в NLP и задачах обработки текста.

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

Многоязычный палиндром с поддержкой Unicode

Строки содержат символы разных языков (кириллица, латиница, эмодзи). Используем регулярное выражение для удаления всего, кроме букв и цифр, и нормализацию.

Пример
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("Madam, in Eden, I'm Adam"))   # True
print(is_palindrome_unicode('???'))                       # True

Пояснение: re.sub с флагом UNICODE корректно обрабатывает юникодные буквы. Для полной совместимости с диакритическими знаками можно добавить unicodedata.normalize.

Ошибка: \w включает также подчеркивание, что может быть нежелательно. Альтернатива - использовать [^\p{L}\p{N}] с библиотекой regex для точного определения категорий Unicode.

Проверка палиндрома для списка (рекурсивно)

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

Пример
def is_palindrome_list(lst):
    if len(lst) <= 1:
        return True
    if lst[0] != lst[-1]:
        return False
    return is_palindrome_list(lst[1:-1])
print(is_palindrome_list([1,2,3,2,1]))  # True
print(is_palindrome_list([1,2,3]))      # False
print(is_palindrome_list([]))           # True

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

Ошибка: срез lst[1:-1] создает новую копию списка, что неэффективно по памяти. Для больших последовательностей лучше использовать итеративный подход с индексами.

Примеры задач по программированию на Python - comments

En
программа python примеры задач (python)