C++ на LeetCode: как решать задачи и прокачать скилл

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему C++ — идеальный язык для LeetCode (и как не провалиться)

Если вы открыли LeetCode и подумали: «Напишу-ка я всё на Python, там лаконично», — стоп. Для хардкорного роста и настоящего понимания алгоритмов C++ даёт фору любому другому языку. Почему? Потому что он заставляет вас думать о памяти, скорости и тонкостях реализации. Никакого «магического» sort() без понимания, как он работает.

В этой статье мы не просто перечислим задачи. Мы покажем, как мыслить на C++ при решении задач LeetCode, какие структуры данных реально нужны, и дадим готовые шаблоны кода. Вы узнаете, почему std::vector — ваш лучший друг, а std::unordered_map — секретное оружие.

Готовы? Поехали.

Топ-5 структур данных C++ для LeetCode

Прежде чем кидаться решать задачи, нужно собрать «арсенал». Вот что реально пригодится в 90% случаев:

  • std::vector — динамический массив. Всё, что связано с последовательностями, интервалами, матрицами.
  • std::unordered_map — хеш-таблица. Для подсчётов, поиска дубликатов, двухсуммных задач.
  • std::set / std::unordered_set — множества. Когда нужно быстро проверять наличие элемента.
  • std::stack / std::queue / std::deque — для обходов, скобочных последовательностей, BFS/DFS.
  • std::pair — незаменим для хранения пар (например, координаты + значение).

Вот пример, как выглядит базовая обёртка для частотного анализа с использованием хеш-таблицы:

#include <unordered_map>
#include <vector>
#include <string>

std::unordered_map<std::string, int> countWords(const std::vector<std::string>& words) {
    std::unordered_map<std::string, int> freq;
    for (const auto& w : words) {
        freq[w]++;
    }
    return freq;
}

Видите? Минимум кода, максимум пользы.

Как подходить к задаче: чек-лист для C++

Ошибка новичка — сразу писать код. Правильный путь — сначала понять структуру данных. Для C++ это критично, потому что неправильный выбор контейнера может стоить вам Time Limit Exceeded (TLE).

Шаг 1. Определите тип задачи

  • Массивы / строки → vector, string
  • Поиск дубликатов → unordered_set
  • Динамическое программирование → vector<vector<int>>
  • Графы → vector<vector<int>> или unordered_map<int, vector<int>>

Шаг 2. Выберите алгоритмическую парадигму

  • Жадный алгоритм — если задача про минимум/максимум
  • Бинарный поиск — для отсортированных данных
  • Два указателя — для интервалов
  • DFS/BFS — для обходов

Шаг 3. Напишите скелет

Не пытайтесь сразу оптимизировать. Сначала рабочее решение, потом — рефакторинг.

Разбор реальной задачи: Two Sum (LeetCode #1)

Классика. Даже если вы её решали, на C++ она раскрывается иначе.

Условие: Дан массив целых чисел nums и целое число target. Верните индексы двух чисел, сумма которых равна target.

Плохое решение (O(n²)):

std::vector<int> twoSum_brute(std::vector<int>& nums, int target) {
    for (int i = 0; i < nums.size(); ++i) {
        for (int j = i + 1; j < nums.size(); ++j) {
            if (nums[i] + nums[j] == target) {
                return {i, j};
            }
        }
    }
    return {};
}

Хорошее решение (O(n) с unordered_map):

#include <unordered_map>

std::vector<int> twoSum(std::vector<int>& nums, int target) {
    std::unordered_map<int, int> seen; // значение -> индекс
    for (int i = 0; i < nums.size(); ++i) {
        int complement = target - nums[i];
        if (seen.find(complement) != seen.end()) {
            return {seen[complement], i};
        }
        seen[nums[i]] = i;
    }
    return {};
}

Почему это круто? Мы используем хеш-таблицу для мгновенного поиска. Обратите внимание на seen.find() — это стандартный паттерн для C++.

Типичные ошибки C++ на LeetCode (и как их избежать)

Вот три грабли, на которые наступают почти все:

Ошибка 1: Забываете про const и ссылки

Если передаёте вектор по значению — получите копию. Для больших данных это катастрофа.

// Плохо: копия
void process(std::vector<int> nums) { ... }

// Хорошо: константная ссылка
void process(const std::vector<int>& nums) { ... }

Ошибка 2: Используете std::map вместо std::unordered_map

std::map — это красно-чёрное дерево (O(log n) на операцию). std::unordered_map — хеш-таблица (O(1) в среднем). Для LeetCode разница колоссальная.

Ошибка 3: Пишете свои велосипеды

Не надо писать сортировку пузырьком. Используйте std::sort — он быстрее и надёжнее.

План обучения C++ для LeetCode за 30 дней

Чтобы не «плавать» в задачах, разбейте подготовку на этапы:

Неделя 1: Освоение контейнеров

  • vector, string, pair
  • Решите 10 лёгких задач на массивы

Неделя 2: Хеш-таблицы и множества

  • unordered_map, unordered_set
  • Задачи: Two Sum, Contains Duplicate, Valid Anagram

Неделя 3: Алгоритмы обхода

  • DFS, BFS на графах
  • Стек, очередь, дек
  • Задачи: Binary Tree Level Order Traversal, Number of Islands

Неделя 4: Динамическое программирование

  • Мемоизация, таблицы DP
  • Задачи: Climbing Stairs, Coin Change, Long

Блоги

Рекомендаций по книгам