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

rust


2

Ссылка на задачу — 1028. Recover a Tree From Preorder Traversal.

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

Дано строковое представление бинарного дерева, полученное в порядке прямого обхода, где:

Например для следующего дерева, представление будет таким: 1-2--3---4-5--6---7

Необходимо восстановить бинарное дерево по этой строке и вернуть его корень.

💡 Идея

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

ответить
3

Ссылка на задачу – 1261. Find Elements in a Contaminated Binary Tree.

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

Дано двоичное дерево, в котором:

Значения всех узлов загрязнены (-1).
Нужно реализовать структуру FindElements, которая:

💡 Идея

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

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

  1. Поиск родителя (parent):

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

ответить
3

Ссылка на задачу — 1980. Find Unique Binary String.
Кайфовая задачка для тех, кто не прогуливал лекции по мат. анализу ☺

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

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

💡 Идея

Используем диагонализацию Кантора:

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

  1. Итерируемся по индексам 0..n.
  2. Берем i-й символ i-й строки.
  3. Инвертируем его ('0' → '1', '1' → '0').
  4. Собираем новые символы в строку и возвращаем её.

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

Визуальный пример

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

impl Solution {
    pub fn find_different_binary_string(nums: Vec<String>) -> String {
        let n = nums.len();

        // Generate a new binary string by flipping the diagonal elements.
        (0..n)
            .map(|i| Self::inverse_char(nums[i].as_bytes()[i] as char))
            .collect()
    }

    fn inverse_char(c: char) -> char {
        match c {
            '0' => '1',
            '1' => '0',
            _ => unreachable!("Unexpected character: {}", c),
        }
    }
}

Tags: #rust #algorithms #math

ответить
3

Ссылка на задачу — 1415. The k-th Lexicographical String of All Happy Strings of Length n.

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

"Счастливая строка" – это строка длины n, состоящая только из символов ['a', 'b', 'c'], в которой нет двух одинаковых подряд идущих символов.
Нужно найти k-ю счастливую строку в лексикографическом порядке, либо вернуть "", если таких строк меньше k.

💡 Идея

Рассмотрим связь счастливых строк с двоичными строками.
Каждая счастливая строка:

Таким образом, двоичное представление k-1 почти полностью определяет структуру требуемой строки (без первого символа).
Мы можем использовать биты 0 и 1 из этого двоичного представления, чтобы выбирать между двумя допустимыми символами при итеративной генерации каждого следующего символа конкретной счастливой строки. 🚀

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

  1. Определяем количество возможных строк с фиксированным первым символом:

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

ответить
3

Очередная задача — 2375. Construct Smallest Number From DI String сходу выглядит переборной, но может быть эффективно реализована за счёт использования графовых алгоритмов.

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

Дан строковый шаблон pattern, состоящий из символов I и D.
Необходимо построить лексикографически наименьшее число длины n+1, используя цифры от 1 до 9 без повторений, которое соответствует следующим требованиям:

💡 Идея

Рассмотрим шаблон как ориентированный граф, где каждая позиция (i) — это вершина.

После построения графа можно выполнить топологическую сортировку, начиная с вершин с нулевой степенью захода.
Чтобы гарантировать лексикографически наименьший порядок, обрабатываем вершины через приоритетную очередь (Min-Heap).

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

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

ответить
3

Продолжаем череду задач на перебор - 1079. Letter Tile Possibilities.

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

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

💡 Идея решения

🧑‍💻 Подробности подхода

  1. Сортировка плиток:
    • Плитки сортируются для того, чтобы одинаковые плитки оказались рядом. Это позволяет нам эффективно группировать их в сегменты.
  2. Группировка плиток:
    • Создаем массив сегментов, где каждый элемент представляет собой количество одинаковых плиток.
    • Например, для строки "AAB" сегменты будут равны [2, 1] (2 плитки "A" и 1 плитка "B").
  3. Бэктрекинг — для каждого сегмента мы:
    • пытаемся использовать плитку (уменьшаем количество плиток в этом сегменте);

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

ответить
3

Ссылка на задачу – 1718. Construct the Lexicographically Largest Valid Sequence.

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

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

💡 Идея

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

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

  1. Рекурсивно заполняем последовательность, начиная с первого свободного индекса.
  2. Используем массив used, который отслеживает, какие числа уже размещены.
  3. Пропускаем занятые позиции.
  4. Проверяем возможность размещения числа заранее, прежде чем выполнять рекурсию.

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

ответить
3

Ссылка на задачу – 1352. Product of the Last K Numbers.

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

Необходимо создать структуру ProductOfNumbers, которая:

Гарантируется, что ответы не приведут к переполнению 32-битного целого.

💡 Идея

Будем использовать префиксные произведения.
Это позволит получать результат за O(1), выполняя деление последних значений.
Но так как деление на 0 запрещено, придётся аккуратно отслеживать этот случай и сбрасывать произведения при появлении нуля.

⚙️ Подход

  1. Используем Vec<i64> для хранения префиксных произведений.
  2. Добавление числа:
    • Если num == 0, очищаем хранилище, так как любое произведение после нуля будет равно нулю.
    • Иначе умножаем предыдущее произведение на текущее число и сохраняем результат.
  3. Вычисление get_product(k):
    • Если k больше количества сохранённых чисел, возвращаем 0.
    • Иначе делим последнее префиксное произведение на значение k шагов назад.

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

ответить
3

Ссылка на задачу – 3066. Minimum Operations to Exceed Threshold Value II.

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

Дан массив nums и число k. Мы можем выполнять следующую операцию, пока в массиве есть хотя бы два элемента:

Необходимо найти количество операций, чтобы все числа в массиве стали ≥ k.

💡 Идея

Мы объединяем два наименьших числа, поэтому важно быстро находить и извлекать их.
Для этого можно использовать очередь с приоритетами (BinaryHeap), но в нашем случае можно действовать эффективнее.

🔹 Заведём две очереди (VecDeque):

Благодаря двум упорядоченным очередям, минимальные элементы можно извлекать за O(1), а вся процедура будет работать эффективнее, чем с BinaryHeap.

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

ответить
3

Ссылка на задачу – 2342. Max Sum of a Pair With Equal Sum of Digits

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

Дан массив положительных чисел nums. Необходимо найти максимальную сумму двух различных элементов, у которых одинаковая сумма цифр. Если таких пар нет — вернуть -1.

💡 Идея решения

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

🔍 Подход к решению

  1. Используем массив max_per_dsum, в котором храним наибольшее число для каждой суммы цифр.
    • Максимальная сумма цифр для i32 — 82, но мы ограничиваем массив сотней для простоты.
  2. Обрабатываем nums за один проход, применяя функциональный стиль с filter_map:
    • вычисляем сумму цифр d_sum для числа n;
    • если уже есть число с таким d_sum, определяем текущую сумму пары и сохраняем обновлённое максимальное число;
    • если это первое число с данным d_sum, просто сохраняем его в max_per_dsum;
    • filter_map отбрасывает неопределённые суммы пар (None), оставляя только валидные.

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

ответить
3

Ссылка на задачу – 1910. Remove All Occurrences of a Substring.

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

Даны две строки s и part. Нужно избавиться от всех вхождений part из s, выполняя следующую операцию:

🐢 Анализ наивного решения

Достаточно несложно быстро набросать следующее решение:

impl Solution {
    pub fn remove_occurrences(mut s: String, part: String) -> String {
        let P = part.len();
        while let Some(idx) = s.find(&part) {
            s.replace_range(idx..idx+P, "");
        }
        s
    }
}

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

1 ответ
3

Ссылка на задачу – 3174. Clear Digits.

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

Дана строка s, содержащая буквы и цифры. Из неё возможно удалять цифры только путем выполнения следующей операции:

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

💡 Идея

Достаточно легко придумать алгоритм, формирующий ответ справа-налево (просто запоминаем, сколько символов нужно скипнуть после встреченных цифр).

Мы же реализуем решение с прямым (слева-направо) обходом строки без необходимости переворачивания результата.

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

  1. Инициализируем буфер размером s.len() (заполняем заглушками '\0').

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

ответить
3

Ссылка на задачу – 2364. Count Number of Bad Pairs.

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

Дан массив nums, где пара индексов (i, j) называется плохой, если выполняется:

Требуется найти общее количество таких плохих пар.

💡 Идея

🛠️ Детали метода

  1. Создаём массив позиционных разностей:
    pos_diff[i]=nums[i]−i
  2. Сортируем массив pos_diff, группируя одинаковые значения.
  3. Используем метод chunk_by для подсчёта частот одинаковых значений.
  4. Для каждой такой частоты count, вычисляем количество хороших пар:
    count×(count−1)/2
  5. Всего существует n × (n - 1) / 2 пар, из них вычитаем хорошие пары и получаем ответ.

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

🔥 Хотя сортировка для подсчёта частот медленнее хеш-таблиц в асимптотике, на практике она быстрее из-за низкой константы!

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

impl Solution {
    pub fn count_bad_pairs(nums: Vec<i32>) -> i64 {
        let n = nums.len() as i64;

        // Compute adjusted values (nums[i] - i) and sort
        let mut pos_diff: Vec<_> = nums.into_iter()
            .enumerate()
            .map(|(idx, num)| num - idx as i32)
            .collect();

        pos_diff.sort_unstable();

        // Count good pairs using `chunk_by`
        let good_pairs: i64 = pos_diff
            .chunk_by(|a, b| a == b)
            .map(|chunk| (chunk.len() as i64 * (chunk.len() as i64 - 1)) / 2)
            .sum();

        // Total pairs - good pairs = bad pairs
        let total_pairs = n * (n - 1) / 2;
        total_pairs - good_pairs
    }
}

Tags: #rust #algorithms #math

ответить
3

Ссылка на задачу ­– 3160. Find the Number of Distinct Colors Among the Balls.

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

Идея 💡

Основная идея заключается в использовании двух хеш-таблиц:

Это позволяет за константное (в среднем) время обновлять информацию при каждом запросе и быстро определять число уникальных цветов.

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

  1. Обновление цвета шарика:
    • При выполнении запроса, если шарик уже был раскрашен, получаем его старый цвет и уменьшаем счётчик в color_counts. Если счётчик для старого цвета становится равным нулю, уменьшаем количество уникальных цветов.

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

4 ответа
3

Ссылка на задачу – 1726. Tuple with Same Product.

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

Дан массив nums из различных положительных чисел. Нужно вернуть количество кортежей (a, b, c, d), таких что произведение a * b равно произведению c * d, при условии, что все элементы кортежа различны.

💡 Идея

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

  1. Подсчет в HashMap:
    • Используем два вложенных цикла для перебора всех уникальных пар (i, j) с условием i < j и вычисляем их произведение.
    • Результаты произведений сохраняем в HashMap, где ключ — это само произведение, а значение — количество его вхождений.
  2. Расчет кортежей:
    • Для каждого произведения с частотой больше 1, добавляем в итоговый результат значение
      4 * frequency * (frequency - 1).
  3. Возврат результата:

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

1 ответ
3

Ссылка на задачу – 1790. Check if One String Swap Can Make Strings Equal.

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

Даны две строки s1 и s2 равной длины. Необходимо определить, можно ли сделать строки равными, совершив не более одного обмена символов в одной из строк.
Обмен — это операция, когда выбираются два индекса в строке и символы на этих позициях меняются местами.

Идея 😊

Основная идея заключается в поиске позиций, на которых символы в строках различаются.

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

  1. Сбор различающихся индексов:
    • Пройдемся по всем индексам строк и соберем в вектор те индексы, на которых символы в s1 и s2 различаются.
      При этом достаточно собрать максимум 3 индекса.
  2. Проверка случаев:
    • Нет различий: Если вектор пуст, строки равны.

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

ответить
3

Ссылка на задачу – 3105. Longest Strictly Increasing or Strictly Decreasing Subarray.

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

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

🤔 Идея

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

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

  1. Разбиение на чанки:
    Используем метод chunk_by для разбиения массива:
    • Для строго возрастающей последовательности используем сравнение a < b.
    • Для строго убывающей последовательности используем сравнение a > b.
  2. Вычисление максимальной длины:
    • Для каждого набора чанков вычисляем длину каждой группы, выбираем максимальную длину для возрастающих и убывающих групп.
  3. Результат:
    • Возвращаем максимум между максимальной длиной возрастающей и максимальной длиной убывающей последовательности.

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

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

impl Solution {
    pub fn longest_monotonic_subarray(nums: Vec<i32>) -> i32 {
        // Group strictly increasing segments using chunk_by
        let max_increasing_len = nums.chunk_by(|a, b| a < b)
            .map(|c| c.len()).max().unwrap_or(0);

        // Group strictly decreasing segments using chunk_by
        let max_decreasing_len = nums.chunk_by(|a, b| a > b)
            .map(|c| c.len()).max().unwrap_or(0);

        max_increasing_len.max(max_decreasing_len) as i32
    }
}

Tags: #rust #algorithms #iterators

1 ответ
3

Следуюшая задача для нашего обзора - 827. Making A Large Island.
Интересный способ для постобработки результатов стандартного поиска в графе.

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

Дан n × n бинарный массив grid, где 1 — это суша, а 0 — вода.
Можно изменить ровно один 0 на 1, после чего необходимо найти размер самого большого острова.
Остров — это группа соседних единичек (соседи считаются по 4-м направлениям).

💡 Идея

1️⃣ Сначала находим и маркируем все острова, присваивая им уникальные ID.
2️⃣ Затем проверяем каждую клетку 0 и считаем, насколько большой станет остров, если заменить её на 1.

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

  1. Маркируем острова с помощью BFS
    • Обход в ширину помечает все клетки острова уникальным ID (начиная с 2).
    • Запоминаем размер каждого острова.

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

ответить
3

Задача - 2493. Divide Nodes Into the Maximum Number of Groups.

📌 Постановка задачи

Дан неориентированный граф с n вершинами, возможно несвязный. Требуется разбить вершины на m групп, соблюдая условия:
✔ Каждая вершина принадлежит ровно одной группе.
✔ Если вершины соединены ребром [a, b], то они должны находиться в смежных группах (|group[a] - group[b]| = 1).
✔ Найти максимальное количество таких групп m.
✔ Вернуть -1, если разбиение невозможно.

💡 Идея

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

  1. Строим граф в виде списка смежности.
  2. Запускаем BFS из каждой вершины (а не только из одной в компоненте) для:
    • Проверки двудольности (по уровням BFS).
    • Поиска максимальной глубины BFS (max_level).
    • Определения уникального идентификатора компоненты (min_index).

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

ответить
3

Следующая задача для разбора - 1462. Course Schedule IV

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

У нас есть numCourses курсов, пронумерованных от 0 до numCourses - 1.
Даны:

Нужно вернуть массив булевых значений, где для каждого запроса ответ — true, если курс u является прямым или косвенным предшественником курса v; или false, если нет.

💡 Идея

Представим зависимости курсов в виде графа, где вершины — это курсы, а ребра указывают на зависимости между ними. Наша цель — определить, существует ли путь между двумя вершинами графа. Для этого можно использовать алгоритм Флойда-Уоршелла, чтобы вычислить транзитивное замыкание графа.

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

  1. Инициализация матрицы зависимостей: Создаем булевую матрицу n x n, где dep_matrix[i][j] обозначает, что курс i является предшественником курса j.
  2. Заполнение прямых зависимостей: На основе массива prerequisites отмечаем прямые зависимости в матрице.

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

ответить
3

Задача, что мы рассмотрим сегодня - 2948. Make Lexicographically Smallest Array by Swapping Elements

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

Лексикографический порядок: Массив a меньше массива b, если на первой позиции i, где они различаются, a[i] < b[i].

💡 Идея:

Будем эксплуатировать следующие замечания:

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

  1. Сортировка индексов: На первом шаге создаём массив sorted_indices, заполняя его значениями [0, 1, ..., n-1]. Затем сортируем этот массив по значениям массива nums, чтобы определить относительный порядок элементов.

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

ответить
3

В очередной задаче для обзора - 802. Find Eventual Safe States нам предстоит найти вершины, не попадающие в циклы графа.

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

Нужно определить безопасные вершины в ориентированном графе.

💡 Идея

Задача решается с помощью обхода графа в глубину (DFS) и вектора состояний.
Каждому узлу присваивается одно из трёх состояний:

  1. Unseen (ещё не обработан);
  2. Processing (в процессе обработки; узлы, являющиеся частью цикла, остаются в этом состоянии и после обработки);
  3. Safe (безопасный).

🔍 Детальное описание подхода

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

ответить
3

В нашей новой задаче - 1765. Map of Highest Peak продолжим закреплять работу с семейством простых графовых алгоритмов.

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

Вам дана матрица isWater размером m×n, где:

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

  1. Высота каждой клетки была неотрицательной.
  2. Высота любой клетки с водой была равна 0.
  3. Абсолютная разница высот у соседних клеток не превышала 1.
  4. Максимальная высота в назначенной карте была как можно больше.

💡 Идея

Мы используем поиск в ширину с несколькими источниками (multi-source BFS), начиная с клеток воды (высота 0).
На каждом шаге ближайшие клетки суши получают высоту на 1 больше текущей.
Этот метод гарантирует, что все клетки суши получают наилучшую из возможных высот, что приводит к максимизации самой высокой высоты в матрице.

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

  1. Инициализация:
    • Создаём очередь и добавляем в неё все клетки воды, помечая их высотой 0.

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

ответить
3

Сегодня в нашей задаче 2017. Grid Game требуется рассчитать оптимальную стратегию в игре с 2 участниками. И большая часть решения опять – "размышления на салфетке".

🖍️ Условие задачи

Дано: двумерный массив grid размером 2 x n, где grid[r][c] представляет количество очков в ячейке (r, c).

Цель первого робота: минимизировать максимальное количество очков, которые сможет собрать второй робот.

💡 Идея

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

  1. Право → Вниз: Сначала пройти весь верхний ряд, а затем спуститься вниз на последней колонке.
  2. Вниз → Право: Спуститься вниз сразу, а затем двигаться вправо вдоль нижнего ряда.

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

ответить
3

В следующей задаче - 2661. First Completely Painted Row or Column можно не симулировать в лоб, и за счёт этого сэкономить память при решении (хоть и не получится асимптотически лучше).

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

example-painting

Необходимо найти первый такой индекс i в массиве arr, при котором:

💡 Идея

Задачу можно переформулировать:

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

ответить

Страница 1 2