Решения задач по 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