Обучение решению задачи с LeetCode уровня Easy
Практическая пошаговая инструкция, как научиться решать задачи самостоятельно, и привести несколько ключевых примеров задач с подробным разбором и кодом на Python.
Как самостоятельно найти и решать задачи Easy
Вот эффективная стратегия, составленная на основе рекомендаций опытных разработчиков из найденных материалов:
- Начните с проверенных списков: Вместо случайных задач используйте структурированные планы обучения на самом LeetCode. Особенно рекомендуют начать с LeetCode 75 или "Top 100 Liked" задач.
- Фильтруйте по сложности и тегам: На странице Problemset установите фильтр Difficulty: Easy. Затем можно выбрать конкретную тему (например, "Array", "String", "Hash Table"), чтобы изучать паттерны.
- Сортируйте по Acceptance Rate: Задачи с более высоким процентом успешных решений (Acceptance), как правило, проще и лучше подходят для старта.
- Изучайте темы последовательно: Сфокусируйтесь на одной фундаментальной теме за раз (массивы, хеш-таблицы, строки), решите 5-7 задач, чтобы закрепить паттерн, и только потом переходите к следующей.
Примеры задач, паттернов и решений на Python
Ниже приведены классические задачи уровня Easy, которые помогут освоить базовые паттерны.
1. Two Sum (Две суммы)
- Паттерн: Использование хеш-таблицы (словаря) для мгновенного поиска.
- Суть: Найти в массиве два числа, сумма которых равна заданному целевому числу. Вернуть их индексы.
def two_sum(nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
# Создаём словарь для хранения: число -> его индекс
num_map = {}
for i, num in enumerate(nums):
complement = target - num # Вычисляем, какое число нам нужно для пары
# Если нужное число уже есть в словаре, пара найдена
if complement in num_map:
return [num_map[complement], i]
# Если нет, сохраняем текущее число и его индекс в словарь
num_map[num] = i
# По условию задачи решение всегда существует, поэтому сюда не попадём
return []
# Пример использования
print(two_sum([2, 7, 11, 15], 9)) # Вывод: [0, 1]
print(two_sum([3, 2, 4], 6)) # Вывод: [1, 2]
Пояснение: Вместо двух вложенных циклов (O(n²)) мы проходим по массиву один раз. Для каждого числа проверяем, не видели ли мы уже число, которое в сумме с текущим даёт target. Это возможно благодаря мгновенному доступу по ключу в словаре (хеш-таблице).
2. Valid Parentheses (Валидные скобки)
- Паттерн: Использование стека (LIFO - "последним пришёл, первым ушёл").
- Суть: Проверить, правильно ли в строке расставлены скобки (), [], {}.
def is_valid(s):
"""
:type s: str
:rtype: bool
"""
# Стек для хранения открывающих скобок
stack = []
# Сопоставление закрывающих скобок с соответствующими открывающими
mapping = {')': '(', ']': '[', '}': '{'}
for char in s:
if char in mapping: # Если символ - закрывающая скобка
# Достаём последнюю открывающую скобку из стека (или заглушку, если стек пуст)
top_element = stack.pop() if stack else '#'
# Сравниваем её с ожидаемой открывающей скобкой
if mapping[char] != top_element:
return False
else: # Если символ - открывающая скобка, кладём в стек
stack.append(char)
# Строка валидна, если после обработки всех символов стек пуст
return not stack
# Пример использования
print(is_valid("()[]{}")) # Вывод: True
print(is_valid("(]")) # Вывод: False
Пояснение: Алгоритм использует стек для отслеживания порядка скобок. Открывающие скобки помещаются в стек. При встрече закрывающей скобки проверяется, соответствует ли она последней открывающей (вершине стека). Если нет или стек пуст — последовательность невалидна.
3. Best Time to Buy and Sell Stock (Лучшее время для покупки и продажи акций)
- Паттерн: Один проход (проход с отслеживанием минимума).
- Суть: Дан массив цен акций. Нужно максимизировать прибыль, купив в один день и продав в другой, более поздний день.
def max_profit(prices):
"""
:type prices: List[int]
:rtype: int
"""
min_price = float('inf') # Инициализируем минимальную цену как бесконечно большую
max_profit = 0 # Инициализируем максимальную прибыль как 0
for price in prices:
# Обновляем минимальную цену, если найдена меньшая
if price < min_price:
min_price = price
# Пробуем продать по текущей цене и обновляем прибыль, если она больше
potential_profit = price - min_price
if potential_profit > max_profit:
max_profit = potential_profit
return max_profit
# Пример использования
print(max_profit([7, 1, 5, 3, 6, 4])) # Вывод: 5 (купить за 1, продать за 6)
Пояснение: Задача решается за один проход. Мы постоянно отслеживаем самую низкую цену (min_price), встреченную к текущему моменту. Для каждой последующей цены мы вычисляем, какую прибыль можно было бы получить, если бы купили по min_price и продали по текущей цене, и обновляем максимальную прибыль (max_profit).
Ключевые советы для эффективного обучения
- Не сидите над одной задачей слишком долго: Если не получается найти решение за 30-40 минут, изучите готовое решение, а затем попробуйте написать код заново самостоятельно.
- Практикуйтесь регулярно: Гораздо эффективнее решать по 1-2 задачи в день, чем 20 задач за выходные.
- Используйте Python: Этот язык рекомендован из-за лаконичного синтаксиса и богатого набора встроенных структур данных, что позволяет сосредоточиться на логике, а не на особенностях языка.
Для дальнейшего изучения рассмотрите следующие темы и связанные с ними задачи Easy:
- Два указателя (Two Pointers): Задачи Reverse String, Valid Palindrome.
- Бинарный поиск (Binary Search): Задача Binary Search.
- Связные списки (Linked Lists): Задачи Reverse Linked List, Merge Two Sorted Lists.
Помните, что успех приходит через последовательное изучение паттернов, а не через механическое решение сотен случайных задач. Удачи в обучении