главная новое лучшее написать

leetcoder

С нами с 26-11-2024
Карма: 436
Постов: 107
Комментариев: 23


💬 О себе

Регулярно выкладываю разборы LeetCode задач с реализацией на Rust.


1

Задача пятого дня Advent of Code - Print Queue.

📘 Часть I. Условие задачи

💡 Идея

Для проверки корректности можно обходить последовательность и накапливать множество страниц, которые должны были уже встретиться раньше.
Если мы наткнемся на одну из них позже зависимой страницы, это нарушение!

📘 Часть II. Условие задачи

Теперь рассмотрим некорректные последовательности страниц.
Их нужно перестроить согласно правилам и взять сумму центральных страниц из корректных порядков.

💡 Идея

Это задача на топологическую сортировку.

Читать дальше →

ответить
3

Задача 4-го дня Advent of Code — Ceres Search.

📌 Часть I. Условие задачи

Нам дано поле из символов. Нужно найти все вхождения слова "XMAS".
Слово может быть записано:

💡 Идея

Для поиска всех таких слов:

📌 Часть II. Условие задачи

Теперь требуется найти не само слово XMAS, а X-образное расположение двух слов "MAS" вокруг символа "A".
Пример расположения:

  M . S

Читать дальше →

ответить
3

Ссылка на задачу с LeetCode — 2179. Count Good Triplets in an Array.

📘 Условие задачи

Даны два массива nums1 и nums2, являющиеся перестановками чисел от 0 до n-1.
Нужно найти количество хороших троек (x, y, z), таких что:

📌 Пример

💡 Идея

Рассматриваем каждое число как средний элемент потенциальной хорошей тройки.
Если знать, сколько подходящих чисел было до него и после него, можно посчитать количество троек с этим числом посередине.

Читать дальше →

ответить
3

Задача третьего дня Advent of Code — Mull It Over.

📘 Часть I. Описание задачи

Необходимо выделить все корректные mul(X,Y) и подсчитать сумму произведений.

💡 Идея

Парсим только строки, точно соответствующие регулярному выражению "mul(\d{1,3},\d{1,3})", остальные пропускаем. После чего результат каждого умножения суммируем.

📘 Часть II. Описание задачи

Кроме mul, в дампе встречаются do() и don't():

По умолчанию mul разрешён. Надо подсчитать только те mul, которые активны в момент встречи.

💡 Идея

Читать дальше →

ответить
3

Задача второго дня Advent of Code — Red-Nosed Reports.

📘 Часть I. Описание задачи

Имеется множество отчётов, каждый из которых представляет собой последовательность целых чисел — уровней. Отчёт считается безопасным, если:

Пример безопасных отчётов:

Пример небезопасных отчётов:

💡 Идея

Необходимо пройтись по каждой последовательности и проверить, являются ли все пары элементов:

Если хотя бы одна из этих проверок не выполняется — отчёт считается небезопасным.

Читать дальше →

ответить
3

100 задач с LeetCode мы уже обозрели. Пора переходить к более тяжёлым наркотикам.
Дальше будем смотреть на задачи из последнего Advent of Code.
Задача первого дня — Historian Hysteria несложная и затравочная 😻.

📘 Условие части I

Даны два списка целых чисел одинаковой длины. Необходимо оценить, насколько они различаются.
Для этого:

Пример:

После сопоставления по возрастанию:

Читать дальше →

ответить
3

Условие задачи — 2874. Maximum Value of an Ordered Triplet II.

📄 Описание задачи

Дан массив целых чисел nums (индексация с нуля).
Нужно найти максимум выражения (nums[i]-nums[j])·nums[k] среди всех троек индексов i < j < k.
Если все такие значения отрицательны, вернуть 0.

💡 Идея

Выражение (nums[i]-nums[j])·nums[k] будет наибольшим, при фиксированном k, если:

Значит, на каждом шаге мы можем поддерживать максимальное значение разности (nums[i]-nums[j]) до текущего индекса и умножать его на nums[k], обновляя лучший результат.

🔍 Детали подхода

  1. Идем по массиву слева направо. На каждом шаге:
    • max_val хранит максимум из всех предыдущих чисел (nums[..i]);
    • max_diff — максимум nums[i]-nums[j] на текущий момент;
    • умножаем max_diff на текущий nums[k] и обновляем best.
  2. Всё делается за один проход, без дополнительных структур данных.

⏱️ Асимптотика

🧾 Исходный код

impl Solution {
    pub fn maximum_triplet_value(nums: Vec<i32>) -> i64 {
        nums.into_iter().fold((0i64, 0, 0), |(best, max_diff, max_val), x| (
            best.max(x as i64 * max_diff as i64),
            max_diff.max(max_val - x),
            max_val.max(x),
        )).0
    }
}

Tags: #rust #algorithms #greedy

ответить
3

Ссылка на задачу — 2140. Solving Questions With Brainpower.

📋 Описание задачи

📌 Пример:

💡 Идея

Читать дальше →

ответить
4

Ссылка на задачу — 2551. Put Marbles in Bags.

📌 Описание задачи

💡 Идея

При разбиении на k подряд идущих мешков мы делаем k - 1 разрез между кусками.
Каждый разрез влияет на итоговую сумму добавлением пары вида weights[i] + weights[i+1],
где i — индекс последнего элемента в предыдущем мешке.

explanation.png

Следовательно, вся задача сводится к выбору k - 1 пар соседних кусков, которые:

Читать дальше →

ответить
3

Ссылка на задачу — 763. Partition Labels.

📄 Описание задачи

💡 Идея

Каждая буква должна присутствовать в одной части.
Значит, можно рассматривать все буквы как интервалы [первая позиция, последняя позиция].
Теперь задача сводится к жадному объединению перекрывающихся интервалов: как только текущий интервал завершился, мы фиксируем подстроку.

🔍 Детали подхода

  1. Проходим по строке один раз, чтобы:
    • определить первую и последнюю позицию каждой буквы;
    • зафиксировать порядок появления символов.
  2. Затем проходим по символам алфавита в порядке первого появления:

Читать дальше →

ответить
3

Условие задачи — 2503. Maximum Number of Points From Grid Queries.

📘 Условие задачи

💡 Идея

Вместо того чтобы запускать поиск заново для каждого запроса, можно:

Такой метод за 1 проход отвечает сразу на все запросы.

🛠️ Детали реализации

  1. Сохраняем исходные индексы запросов и сортируем их по значениям.

Читать дальше →

ответить
4

Ссылка на задачу — 2780. Minimum Index of a Valid Split.

📘 Описание задачи

💡 Идея

Для эффективного поиска доминирующего элемента хорошо подходит алгоритм большинства голосов Бойера — Мура.
Зная доминирующий элемент, можно пройти по массиву и в каждой возможной точке разделения отслеживать:

🔍 Детали подхода

  1. Применяем алгоритм голосования большинства для нахождения доминанты.
  2. Подсчитываем точное количество его вхождений, чтобы использовать для отслеживания остатка справа.

Читать дальше →

ответить
3

Ссылка на задачу — 2033. Minimum Operations to Make a Uni-Value Grid.

📌 Описание задачи

Дан двумерный массив grid размером m x n, а также число x.
За одну операцию можно прибавить или

Читать дальше →

ответить
3

Ссылка на задачу — 3394. Check if Grid can be Cut into Sections.

📌 Описание задачи

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

Если такие разрезки возможны, вернуть true, иначе — false.

Пример

💡 Идея

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

Читать дальше →

ответить
4

Ссылка на задачу — 3169. Count Days Without Meetings.

📌 Описание задачи

Нужно посчитать количество дней, когда сотрудник свободен от встреч и может работать.

💡 Идея

Мы сортируем встречи по дню начала, чтобы затем обходить их в порядке возрастания.
Это позволяет использовать метод заметания линии как эффективный способ вычислить количество свободных дней между встречами.

🚀 Детали подхода

1️⃣ Сортируем встречи по начальной дате.
2️⃣ Проходим по списку встреч, отслеживая next_free (следующий свободный день).
3️⃣ Подсчитываем разрывы между next_free и началом следующей встречи.
4️⃣ Обновляем next_free после каждой встречи, сдвигая его на день после её окончания.
5️⃣ Добавляем свободные дни после последней встречи.

⏳ Асимптотика

💻 Исходный код

impl Solution {
    pub fn count_days(days: i32, mut meetings: Vec<Vec<i32>>) -> i32 {
        meetings.sort_unstable_by_key(|meet| meet[0]);

        let (next_free, free_count) = meetings.into_iter()
            .fold((1, 0), |(next_free, free_count), meet| {
                let [start, end] = meet[..2] else { unreachable!("bad meet format") };
                let gap = (start - next_free).max(0);
                let next_free = next_free.max(end + 1);
                (next_free, free_count + gap)
        });

        free_count + (days - next_free + 1).max(0)
    }
}

Tags: #rust #algorithms #counting

ответить
3

Ссылка на задачу — 2115. Find All Possible Recipes from Given Supplies.
В этой задаче для эффективного решения важно не только выбрать эффективный алгоритм, но и аккуратно разложить строки по необходимым структурам данных, избежать лишних копирований и обеспечить ясную картину ownership'a за объектами.

📌 Описание задачи

💡 Идея

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

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

🔍 Детали подхода

  1. Предобработка входных данных:
    • Создаём хеш-таблицу для быстрого доступа к индексу каждого рецепта.
    • Добавляем начальные запасы в кеш доступных ингредиентов.

Читать дальше →

ответить
3

Ссылка на задачу — 3108. Minimum Cost Walk in Weighted Graph.

📌 Описание задачи

Пример

💡 Идея

Читать дальше →

1 ответ
4

Ссылка на задачу — 3191. Minimum Operations to Make Binary Array Elements Equal to One I.

📌 Описание задачи

Пример:

💡 Идея

Читать дальше →

ответить
3

Ссылка на задачу — 2401. Longest Nice Subarray.

📌 Описание задачи

Дан массив nums, состоящий из целых чисел.
Нужно найти наибольший подмассив, в котором ни одна пара чисел не имеет общих установленных битов
(т.е. их побитовое И (&) равно 0).

Пример

💡 Идея

Будем решать задачу в чистом функциональном стиле, используя технику скользящего окна.

Читать дальше →

1 ответ
4

Ссылка на задачу — 2594. Minimum Time to Repair Cars.

❓ Описание задачи

Дано:

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

💡 Идея

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

Однако это распределение не покрывает все машины. Для распределения оставшихся машин мы посчитаем для каждого механика оценку времени его работы, если взять несколько дополнительных машин (тем больше, чем больше вес механика). После остаётся лишь выбрать k-ое минимальное значение среди посчитанных времён с помощью алгоритма «QuickSelect» (любезно реализованного в стандартной библиотеке Rust).

🔍 Детали подхода

1️⃣ Быстрое распределение — вычисляем вес каждого механика и распределяем машины пропорционально.

Читать дальше →

ответить
3

Ссылка на задачу — 3480. Maximize Subarrays After Removing One Conflicting Pair.

📌 Описание задачи

Пример

💡 Идея

Читать дальше →

ответить
3

Ссылка на задачу — 2226. Maximum Candies Allocated to K Children.

📌 Описание задачи

Дан массив candies, где candies[i] — это количество конфет в i-й куче. Нужно раздать конфеты k детям так, чтобы каждый ребёнок получил одинаковое количество конфет и все конфеты одного ребёнка были взяты из одной кучи.
Требуется найти максимальное возможное количество конфет, которое может получить каждый ребёнок.

💡 Идея

Перебор всех возможных вариантов распределения неэффективен. Вместо этого воспользуемся бинарным поиском по ответу:

Будем проверять, можно ли выдать каждому ребёнку candies_per_child конфет.
Если да, увеличиваем candies_per_child, иначе уменьшаем.

🛠 Подробности метода

  1. Вычисляем total_candies — суммарное количество конфет.
  2. Условие быстрого выхода: если total_candies < k, сразу возвращаем 0.
  3. Определяем предикат can_share, который проверяет, можно ли распределить candies_per_child конфет на k детей.

Читать дальше →

ответить
3

Ссылка на задачу — 3356. Zero Array Transformation II.

📝 Описание задачи

Дан массив nums длины N и список запросов queries, каждый из которых задаётся как [li, ri, vali]. Запрос означает, что значения в диапазоне [li, ri] можно уменьшить на любое число от 0 до vali независимо друг от друга.

Нужно найти минимальное число первых запросов k, после которых nums может превратится в массив, состоящий только из нулей. Если это невозможно — вернуть -1.

💡 Идея

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

Чтобы минимизировать количество обработанных запросов, будем использовать жадную стратегию обработки запросов:

⚙️ Детали подхода

  1. Используем массив updates (N+1 элементов), где updates[i] хранит последовательные изменения к декременту значений.

Читать дальше →

ответить
3

Ссылка на задачу — 3479. Fruits Into Baskets III.

📌 Описание задачи

У нас есть два массива:

Нужно распределить фрукты по корзинам слева направо по следующим правилам:

Требуется вернуть количество неразмещённых фруктов.

💡 Идея

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

🔍 Подробности подхода

  1. Построение дерева отрезков 🌳:
    • Создаём дерево отрезков для максимумов на интервалах, инициализируюя его вместимостями корзин.

Читать дальше →

ответить
3

Ссылка на задачу — 3306. Count of Substrings Containing Every Vowel and K Consonants II.

📌 Условие задачи

Дана строка word и неотрицательное число k.
Необходимо подсчитать количество подстрок, в которых встречаются все гласные буквы ('a', 'e', 'i', 'o', 'u') хотя бы по одному разу и ровно k согласных.

💡 Идея

Будем использовать подход «скользящего окна», отслеживая позиции последних появлений гласных и согласных букв.
Это позволяет эффективно перемещать границы окна и быстро проверять условия задачи при изменении количества согласных и наличии всех гласных.

🛠️ Детали подхода

  1. Для каждой гласной буквы сохраняется её последняя позиция.
  2. Для согласных используется итератор, последовательно предоставляющий позиции согласных в строке.
  3. Если количество согласных становится больше k, левая граница окна перемещается вперёд.
  4. При каждом совпадении условий (ровно k согласных и присутствуют все гласные) подсчитывается количество допустимых подстрок.

⏳ Асимптотика

Читать дальше →

ответить

Страница 1 2 3 4 5