Решения задач по Python с разбором типовых ошибок

Раздел: Практические задания -> Алгоритмы

Разбор задач с примерами кода

Представленные ниже задачи помогают освоить базовые алгоритмы и приемы работы с данными в Python. Для каждой задачи указан основной способ решения, альтернативные варианты и возможные сложности.

Поиск максимального элемента в списке

Как найти максимальное значение без встроенной функции max?

Основная идея состоит в последовательном сравнении элементов. Первый элемент принимается за текущий максимум, затем каждый следующий элемент сравнивается с ним.

def find_max(arr):
    if not arr:
        return None
    max_value = arr[0]
    for current in arr[1:]:
        if current > max_value:
            max_value = current
    return max_value

print(find_max([4, 9, 2, 7]))

Python примеры задания (примеры задач по python с решениями)

9

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

Как получить максимум с использованием функции reduce?

Функция reduce из модуля functools последовательно применяет бинарную операцию к элементам последовательности. В качестве операции задается сравнение двух чисел.

from functools import reduce

numbers = [4, 9, 2, 7]
result = reduce(lambda a, b: a if a > b else b, numbers)
print(result)
9

Примечание. Если список пуст, функция find_max возвращает None. В reduce для пустой последовательности требуется указать начальное значение, иначе возникнет ошибка TypeError. Использование среза arr[1:] создает копию списка, для больших списков это затратно по памяти. Цикл с индексами позволяет избежать копии, но менее удобен.

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

Как проверить, что строка читается одинаково в обе стороны?

Строка приводится к нижнему регистру, затем сравниваются символы с двух концов. Цикл движется навстречу до центра.

def is_palindrome(text):
    text = text.lower()
    left = 0
    right = len(text) - 1
    while left < right:
        if text[left] != text[right]:
            return False
        left += 1
        right -= 1
    return True

print(is_palindrome('Racecar'))
True

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

Сравнение строки с собственной перевернутой копией является короткой альтернативой. Для переворота используется срез [::-1].

def is_palindrome_slice(text):
    return text.lower() == text.lower()[::-1]

print(is_palindrome_slice('Racecar'))
True

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

Вычисление суммы цифр числа

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

Используются операции взятия остатка от деления на 10 и целочисленного деления на 10. Остаток добавляется к сумме, затем число уменьшается.

def sum_digits(number):
    number = abs(number)
    total = 0
    while number > 0:
        total += number % 10
        number //= 10
    return total

print(sum_digits(12345))
15

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

Строковое представление позволяет обойтись без арифметики. Каждый символ преобразуется обратно в целое число и суммируется.

def sum_digits_str(number):
    return sum(int(digit) for digit in str(abs(number)))

print(sum_digits_str(12345))
15

Без вызова abs отрицательное число добавит знак минус в строку, и int('-') вызовет ValueError в варианте со строкой. В арифметическом варианте знак не попадет в цикл, поэтому результат будет содержать только сумму модуля. Для числа 0 первый вариант вернет 0, так как цикл не выполнится.

Сортировка списка словарей по значению

Как упорядочить записи по возрасту?

Встроенная функция sorted принимает ключ сортировки. Лямбда-функция возвращает значение возраста для каждого словаря.

people = [
    {'name': 'Анна', 'age': 25},
    {'name': 'Иван', 'age': 19},
    {'name': 'Петр', 'age': 30}
]
people_sorted = sorted(people, key=lambda person: person['age'])
print(people_sorted)
[{'name': 'Иван', 'age': 19}, {'name': 'Анна', 'age': 25}, {'name': 'Петр', 'age': 30}]

Как отсортировать с помощью itemgetter?

Функция itemgetter из модуля operator создает объект, извлекающий заданное поле. Такой способ считается более быстрым при большом количестве элементов.

from operator import itemgetter

people_sorted = sorted(people, key=itemgetter('age'))
print(people_sorted)
[{'name': 'Иван', 'age': 19}, {'name': 'Анна', 'age': 25}, {'name': 'Петр', 'age': 30}]

Обращение person['age'] вызывает ошибку KeyError, если поле отсутствует. Лямбда-функция может использовать get с значением по умолчанию: key=lambda p: p.get('age', 0). itemgetter не предоставляет значение по умолчанию легко, поэтому для неполных данных удобнее лямбда.

Генерация последовательности Фибоначчи

Как создать список первых чисел Фибоначчи?

Два предыдущих числа хранятся в переменных a и b. На каждом шаге a добавляется в список, затем a и b сдвигаются.

def fibonacci(count):
    result = []
    a, b = 0, 1
    for _ in range(count):
        result.append(a)
        a, b = b, a + b
    return result

print(fibonacci(10))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Как получить генератор чисел Фибоначчи?

Генератор вычисляет значения по одному и не хранит весь список в памяти. Это удобно при больших значениях count.

def fibonacci_gen(count):
    a, b = 0, 1
    for _ in range(count):
        yield a
        a, b = b, a + b

print(list(fibonacci_gen(10)))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Рекурсивное вычисление чисел Фибоначчи без мемоизации имеет экспоненциальную сложность. При count, равном 30 или более, время выполнения становится заметным. Для генератора важно не забыть обернуть его в list, чтобы увидеть результат сразу.

Проверка числа на простоту

Как определить, является ли число простым?

Достаточно проверить делители от 2 до квадратного корня из числа. Если делитель найден, число составное.

def is_prime(number):
    if number < 2:
        return False
    for divisor in range(2, int(number ** 0.5) + 1):
        if number % divisor == 0:
            return False
    return True

print(is_prime(17))
True

Как проверить простоту с помощью all?

Функция all возвращает True, если все элементы переданного выражения истинны. Для этого создается генератор остатков от деления.

def is_prime_all(number):
    return number > 1 and all(number % divisor != 0 for divisor in range(2, int(number ** 0.5) + 1))

print(is_prime_all(17))
True

Для number, равного 1, первый вариант возвращает False благодаря проверке number < 2. Во втором варианте без number > 1 функция вернет True, потому что all от пустой последовательности считается True. Границу int(number ** 0.5) необходимо увеличить на единицу, чтобы включить полный квадрат делителя.

Удаление дубликатов с сохранением порядка

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

Множество seen хранит уже встреченные элементы. Если элемент встречается впервые, он добавляется в результат.

def unique_preserve(items):
    seen = set()
    result = []
    for item in items:
        if item not in seen:
            seen.add(item)
            result.append(item)
    return result

print(unique_preserve([3, 1, 3, 2, 1, 5]))
[3, 1, 2, 5]

Как использовать dict.fromkeys для удаления дубликатов?

Словарь сохраняет порядок вставки ключей с Python 3.7. Метод fromkeys создает словарь с элементами в качестве ключей, а list возвращает ключи в порядке добавления.

items = [3, 1, 3, 2, 1, 5]
result = list(dict.fromkeys(items))
print(result)
[3, 1, 2, 5]

Если элемент является нехэшируемым, например вложенным списком, set не сможет его сохранить. dict.fromkeys также требует хэшируемые ключи. Для нехэшируемых элементов понадобится алгоритм с полным сравнением элементов, что увеличивает время выполнения до O(n^2).

Подсчет частоты слов в файле

Как посчитать, какие слова встречаются в тексте чаще всего?

Текст читается из файла, разбивается на слова, затем используется Counter для подсчета.

from collections import Counter

with open('text.txt', 'r', encoding='utf-8') as file:
    words = file.read().split()
counter = Counter(words)
print(counter.most_common(3))

Как посчитать слова с обычным словарем?

Для каждой строки файла выполняется разбиение, и счетчик обновляется через get.

word_counts = {}
with open('text.txt', 'r', encoding='utf-8') as file:
    for line in file:
        for word in line.split():
            word_counts[word] = word_counts.get(word, 0) + 1
print(word_counts)

Метод file.read() загружает весь файл в память. Для больших файлов построчное чтение снижает нагрузку. При подсчете важно учитывать регистр и пунктуацию, иначе слова «Привет» и «привет» будут считаться разными. Для очистки слов используется метод strip с набором символов.

Преобразование элементов списка с помощью map

Как возвести все числа списка в квадрат?

Функция map применяет функцию к каждому элементу и возвращает итератор. Обертывание в list формирует список.

numbers = [1, 2, 3, 4]
squares = list(map(lambda x: x ** 2, numbers))
print(squares)
[1, 4, 9, 16]

Как записать то же самое через list comprehension?

Генератор списка выполняет преобразование и фильтрацию в одной конструкции. Такой вариант часто читается легче.

numbers = [1, 2, 3, 4]
squares = [x ** 2 for x in numbers]
print(squares)
[1, 4, 9, 16]

map из Python 3 возвращает ленивый итератор, поэтому без list результат не отобразится. Лямбда-функция с большим количеством операций делает код менее понятным. list comprehension применяется и для фильтрации, например [x for x in numbers if x > 2].

Обход всех файлов в дереве каталогов

Как получить полные пути ко всем файлам внутри папки?

Модуль os возвращает кортежи (root, dirs, files) при обходе дерева. Для каждого файла создается путь через os.path.join.

import os

for root, dirs, files in os.walk('.'):
    for file_name in files:
        print(os.path.join(root, file_name))

Как использовать pathlib для обхода каталогов?

Метод rglob возвращает все пути, соответствующие шаблону. Проверка is_file отсекает папки.

from pathlib import Path

for path in Path('.').rglob('*'):
    if path.is_file():
        print(path)

os.walk включает скрытые папки и файлы, если их не отфильтровать. pathlib.Path является объектом, поэтому для работы со строкой требуется str(path). При обходе большого дерева рекурсия модуля pathlib может быть медленнее, чем итеративный os.walk.

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

Здесь представлены более сложные и редкие примеры использования Python для алгоритмических задач. Каждый пример содержит код и результат выполнения.

Индексы элементов для заданной суммы

Дан список целых чисел и целевая сумма. Находятся индексы двух элементов, дающих в сумме целевое значение. Решение с одним проходом использует словарь для сохранения уже встреченных чисел.

Пример
def two_sum(nums, target):
    seen = {}
    for index, value in enumerate(nums):
        complement = target - value
        if complement in seen:
            return [seen[complement], index]
        seen[value] = index
    return []

nums = [2, 7, 11, 15]
print(two_sum(nums, 9))
[0, 1]

Сложность алгоритма O(n), так как каждый элемент обрабатывается один раз.

Решето Эратосфена

Для нахождения всех простых чисел до N создается булев список, где False обозначает составное число. Кратные каждого простого числа вычеркиваются.

Пример
def sieve(limit):
    if limit < 2:
        return []
    is_prime = [True] * (limit + 1)
    is_prime[0] = is_prime[1] = False
    for number in range(2, int(limit ** 0.5) + 1):
        if is_prime[number]:
            for multiple in range(number * number, limit + 1, number):
                is_prime[multiple] = False
    return [number for number, prime in enumerate(is_prime) if prime]

print(sieve(30))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

Проверка скобочной последовательности

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

Пример
def is_balanced(text):
    brackets = {'(': ')', '[': ']', '{': '}'}
    stack = []
    for character in text:
        if character in brackets:
            stack.append(character)
        elif character in brackets.values():
            if not stack or brackets[stack.pop()] != character:
                return False
    return not stack

print(is_balanced('[({hello})]'))
True

В конце стек должен быть пустым, иначе количество скобок не совпадает.

Транспонирование матрицы

Операция transpose превращает строки матрицы в столбцы. Генератор списка собирает элементы по номерам столбцов.

Пример
def transpose(matrix):
    return [list(row) for row in zip(*matrix)]

matrix = [
    [1, 2, 3],
    [4, 5, 6]
]
print(transpose(matrix))
[[1, 4], [2, 5], [3, 6]]

Сжатие повторяющихся символов

Код подсчитывает количество подряд идущих одинаковых символов и формирует строку вида символ+количество.

Пример
def rle_encode(text):
    if not text:
        return ''
    result = []
    count = 1
    for index in range(1, len(text)):
        if text[index] == text[index - 1]:
            count += 1
        else:
            result.append(text[index - 1] + str(count))
            count = 1
    result.append(text[-1] + str(count))
    return ''.join(result)

print(rle_encode('aaabbc'))
a3b2c1

Замер времени выполнения функции

Декоратор оборачивает функцию и выводит время, затраченное на выполнение. Внутренняя функция сохраняет имя и аргументы исходной функции через *args, **kwargs.

Пример
import time

def timeit(func):
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        print(f'{func.__name__}: {elapsed:.6f} секунд')
        return result
    return wrapper

@timeit
def compute_sum(n):
    return sum(range(n))

print(compute_sum(1000000))
compute_sum: 0.021234 секунд
499999500000

Время выполнения в каждом запуске отличается.

Мемоизация рекурсивных функций

Декоратор lru_cache сохраняет результаты вызовов функции. Это ускоряет рекурсивные вычисления, например для чисел Фибоначчи.

Пример
from functools import lru_cache

@lru_cache(maxsize=None)
def fib(number):
    if number < 2:
        return number
    return fib(number - 1) + fib(number - 2)

print(fib(50))
12586269025

Кэширование исключает повторное выполнение одних и тех же вычислений.

Пересечение двух списков

Множества поддерживают операцию пересечения, результат не сохраняет порядок. Для сохранения порядка применяется фильтрация по множеству.

Пример
list_a = [1, 2, 3, 4]
list_b = [3, 4, 5, 6]

intersection_set = sorted(set(list_a) & set(list_b))
print(intersection_set)

set_b = set(list_b)
intersection_ordered = [item for item in list_a if item in set_b]
print(intersection_ordered)
[3, 4]
[3, 4]

Генерация комбинаций и перестановок

combinations из itertools создает кортежи длиной r без повторений. permutations учитывает порядок.

Пример
from itertools import combinations, permutations

items = [1, 2, 3]
print(list(combinations(items, 2)))
print(list(permutations(items, 2)))
[(1, 2), (1, 3), (2, 3)]
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

Случайная строка для токена

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

Пример
import secrets
import string

alphabet = string.ascii_letters + string.digits
random_string = ''.join(secrets.choice(alphabet) for _ in range(12))
print(random_string)
K7aF2tR9QpNw

Результат каждого запуска будет другим.

Поиск пропущенного числа

Если дан список чисел от 1 до n, в котором отсутствует одно значение, его можно найти через сумму.

Пример
def find_missing(numbers, n):
    expected_sum = n * (n + 1) // 2
    actual_sum = sum(numbers)
    return expected_sum - actual_sum

print(find_missing([1, 2, 3, 5, 6], 6))
4

Двоичное представление числа

Встроенная функция bin возвращает строку с префиксом '0b'. Для подсчета единиц используется count.

Пример
number = 10
binary = bin(number)
print(binary)
print(binary.count('1'))
0b1010
2

Примеры задач по Python с решениями - comments

En
Python примеры задания (python)