главная новое лучшее написать
неделя месяц год вечное
посты пользователи ответы
3

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

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

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

Идея 😊

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

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

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

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

ответить
3

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

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

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

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

💡 Идея

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

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

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

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

ответить
3

Сегодня мы решаем задачу 2924. Find Champion II

🏆 Задача:

В турнире n команд представлены как вершины DAG (ориентированного ацикличного графа). Если команда a сильнее команды b, это отображается направленным ребром от a к b. Требуется найти чемпиона турнира — вершину, из которой достижимы все остальные вершины. Если чемпиона нет или их несколько, вернуть −1.

😊 Идея:

В DAG вершина с отсутствующими входящими рёбрами (in_degree = 0) является источником. Если в графе ровно один источник, он становится кандидатом в чемпионы, так как из него достижимы все остальные вершины
(Нетривиальный момент: это утверждение не верно в общем случе, но в случае DAG его несложно доказать).
Если источников больше или ни одного, чемпиона не существует.

Сложность

Исходный код решения

impl Solution {
    pub fn find_champion(n: i32, edges: Vec<Vec<i32>>) -> i32 {
        let mut in_degree = vec![0; n as usize];

        // Calculate in-degrees for each node
        for e in &edges {
            in_degree[e[1] as usize] += 1;
        }

        // Identify the potential champion
        let mut champion = -1;
        let mut n_champions = 0;

        for (node, &degree) in in_degree.iter().enumerate() {
            if degree == 0 {
                champion = node as i32;
                n_champions += 1;
            }
        }

        // There must be exactly one node with in-degree 0
        if n_champions == 1 {
            champion
        } else {
            -1
        }
    }
}

ответить
3

Сегодня на очереди задача 2825. Make String a Subsequence Using Cyclic Increments.

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

Даны две строки str1 и str2. Нужно определить, можно ли сделать str2 подпоследовательностью строки str1, выполнив не более одной операции циклического увеличения произвольного набора символов в str1.
Циклический сдвиг означает, что 'a' становится 'b', 'b''c', ..., 'z''a'.

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

Задача почти идентична проверке подпоследовательности в строке. Единственное отличие — сравнение символов становится чуть сложнее из-за необходимости учитывать циклический сдвиг.
Мы выделяем проверку совпадения символов в отдельный метод, а в остальном используем стандартный алгоритм проверки подпоследовательности.

Реализация подхода 🚀

  1. Используем два итератора для последовательного прохода по символам строк.
  2. Для сравнения символов применяем отдельную функцию, учитывающую как прямое совпадение, так и циклический сдвиг.
  3. При совпадении текущего символа строки str2 с символом из str1, переходим к следующему символу в str2.
  4. Если все символы str2 найдены в str1 в правильном порядке, возвращаем true, иначе — false.

Сложность алгоритма 📊

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

ответить
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

Наша новая задача – 2425. Bitwise XOR of All Pairings решается "размышлениями на салфетке" и потом очень быстро и просто программируется.

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

Даны два массива nums1 и nums2, содержащие неотрицательные числа. Для каждой пары чисел, взятых из этих массивов, вычисляется побитовый XOR. Нужно вернуть результат XOR всех таких пар.

🧠 Идея

XOR обладает полезными свойствами:

Только если длина одного массива нечётная, элементы второго массива оказывают влияние на результат, так как они "непарные".
В итоге вклад в результат зависит от длины второго массива для каждого массива из входной пары.

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

  1. Найти длины массивов nums1 и nums2.
  2. Если длина nums2 нечётная, XOR всех элементов nums1 добавляется в результат.
  3. Если длина nums1 нечётная, XOR всех элементов nums2 добавляется в результат.
  4. Возвратить результат как итоговый XOR.

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

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

use std::ops::BitXor;

impl Solution {
    pub fn xor_all_nums(nums1: Vec<i32>, nums2: Vec<i32>) -> i32 {
        let len_nums1 = nums1.len();
        let len_nums2 = nums2.len();

        // Initialize result as 0
        let mut result = 0;

        // If nums1 has an odd number of elements, XOR all elements of nums2
        if len_nums1 % 2 == 1 {
            result ^= nums2.into_iter().fold(0, i32::bitxor);
        }

        // If nums2 has an odd number of elements, XOR all elements of nums1
        if len_nums2 % 2 == 1 {
            result ^= nums1.into_iter().fold(0, i32::bitxor);
        }

        result
    }
}

ответить
3

Задача на сегодня 2657. Find the Prefix Common Array of Two Arrays решается в лоб, но иногда стоит рассматривать и такие простые!

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

Даны две перестановки целых чисел A и B длины n. Необходимо вычислить массив общего префикса C, где C[i] равен количеству чисел, присутствующих в обеих перестановках на индексах от 0 до i.

Пример:

💡 Идея

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

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

  1. Создаем два булевых массива seen_in_a и seen_in_b длины n + 1 для отслеживания элементов, уже встреченных в A и B.
  2. Проходим по массивам A и B одновременно:
  3. Помечаем текущие элементы A[i] и B[i] как "увиденные".
  4. Увеличиваем счетчик общих элементов, если текущий элемент уже был встречен в другом массиве.
  5. На каждом шаге добавляем текущее значение счетчика общих элементов в результат.

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

ответить
3

Последняя в уходящем году задача 983. Minimum Cost For Tickets требует от нас несложного сочетания техник динамического программирования и скользящего окна.

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

У вас есть запланированные дни поездок в течение года, указанные в массиве days. Билеты можно приобрести по следующим ценам:

Необходимо определить минимальные затраты, чтобы покрыть все дни из списка days.

💡 Идея

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

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

  1. Создаем массив dp, где dp[i] хранит минимальную стоимость поездок для первых i дней.

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

ответить
3

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

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

Пример

💡 Идея

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

ответить
3

Очередная наша задача — 2579. Count Total Number of Colored Cells, как ни странно, красиво решается на шахматной доске ☺.

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

Дана бесконечная двумерная сетка с неокрашенными клетками. В течение n минут выполняются следующие действия:

Необходимо вычислить количество окрашенных клеток после n минут.

🧠 Идея

Если рассмотреть процесс закрашивания клеток на шахматной доске, можно увидеть, что в момент n окрашенные клетки образуют два наложенных квадрата:

Сумма площадей этих двух квадратов и дает общее количество окрашенных клеток.

chess-pattern-s.png

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

Применяем формулу: Total = n²+(n−1)²

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

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

impl Solution {
    pub fn colored_cells(n: i32) -> i64 {
        let n = n as i64;
        n*n + (n-1)*(n-1)
    }
}

Tags: #rust #algorithms #math

ответить
3

Сегодня нам предстоит несложная задача - 2182. Construct String With Repeat Limit. Но технически она получилась муторной - требует от программиста очень аккуратного подхода к себе :)

Задача 📜

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

Подход 🚀

  1. Подсчёт частоты символов:
    • Используем массив размера 256, чтобы подсчитать количество вхождений каждого байта (символа).
  2. Жадный выбор символов:
    • Обходим пространство символов (0–255), начиная с самого большого.
    • Добавляем текущий символ в результат до repeat_limit раз или пока его количество не исчерпается.
    • Если нужно "разорвать" последовательность, вставляем следующий по величине символ, уменьшая его количество.
  3. Эффективный поиск следующего символа:
    • Вспомогательная функция find_last_valid_index ищет ближайший допустимый символ с ненулевой частотой, используя знание о текущем символе как ускоряющую подсказку.

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

2 ответа
3

Наступление зимы отметим разбором простой задачи 1346. Check If N and Its Double Exist.

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

Дан массив целых чисел arr. Нужно определить, существуют ли такие индексы i и j, что:
- i≠j,
- arr[i]=2⋅arr[j].

Обзор решения 🚀

Решение использует два простых прохода по массиву:

  1. Первый проход:
    • Создаем хеш-таблицу, где для каждого элемента записываем количество его удвоенных значений.
  2. Второй проход:
    • Проверяем, существует ли текущий элемент в хеш-таблице.
    • Для нуля (0) дополнительно проверяем, встречается ли он в массиве как минимум дважды (так как 2⋅0=0).

Временная сложность ⏱️

Пространственная сложность 📦

Исходый код решения

use std::collections::HashMap;

impl Solution {
    pub fn check_if_exist(arr: Vec<i32>) -> bool {
        let mut double_map = HashMap::new();

        // Populate the map with counts of doubled values
        for &num in &arr {
            *double_map.entry(2 * num).or_insert(0) += 1;
        }

        // Check for the required condition
        for &num in &arr {
            if num == 0 {
                // Special case for 0 (2 * 0 == 0)
                if *double_map.get(&0).unwrap_or(&0) > 1 {
                    return true;
                }
            } else if double_map.get(&num).is_some() {
                return true;
            }
        }

        false
    }
}

1 ответ
3

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

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

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

Пример

💡 Идея

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

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

1 ответ
3

Очередная задача: 2290. Minimum Obstacle Removal to Reach Corner.

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

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

🔑 Идея

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

📋 Подробное описание подхода

  1. Инициализация: Мы создаем две очереди: front и back. Во front помещаем клетки, которые можно пройти без удаления препятствий, а в back — клетки, для которых потребуется удалить препятствие.
  2. Поиск в ширину (BFS):
    • Начинаем с верхнего левого угла и устанавливаем расстояние для этой клетки в 0 (т.е. препятствий еще не удалено).
    • Если клетка пустая (значение 0), мы добавляем её в front. Если клетка — препятствие (значение 1), то в back.

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

ответить
3

Сегодня решаем задачу 2054. Two Best Non-Overlapping Events. Будем закреплять двоичный поиск ;)

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

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

💡 Идея

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

🛠️ Подход

  1. Сортировка событий: По end_time в порядке убывания.
  2. Предобработка максимальных ценностей: Создаём массив max_vals с накопленной максимальной ценностью событий (справа-налево).
  3. Итерация и поиск:
    • Для каждого события находим первое, заканчивающееся раньше его, через двоичный поиск.
    • Суммируем ценности текущего события и накопленной максимальной ценности по найденному индексу, обновляя общий максимум.

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

ответить
3

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

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

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

💡 Идея

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

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

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

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

ответить
3

Следуюшая задача для нашего разбора: 2270. Number of Ways to Split Array.

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

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

Идея 💡

Вместо того чтобы каждый раз вычислять суммы левой и правой частей массива, мы используем баланс для их трекинга.
Изначально баланс равен −total_sum, где total_sum — сумма всех элементов массива. На каждом шаге баланс обновляется с помощью текущего элемента, а проверка условий выполняется через простое сравнение баланса с нулём.

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

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

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

ответить
3

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

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

Идея 💡

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

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

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

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

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

4 ответа
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

Спасибо загадочному пользователюleetcoder, здесь опять есть какая-то жизнь. По такому случаю попробуем сюда писать в формате классического web log, вдруг получится не бросить?

Прикольная статья про силу воли и выгорание. Как всегда на lesswrong, длинновато и напоминает домашнюю философию, но основная мысль крайне простая и что-то в ней есть.

У каждого человека есть "бюджет" силы воли. Внутренний нарратор-планировщик, он же "Система 2", когда вы хотите сделать что-то неприятное, берёт кредит из этого "бюджета". Когда в вашей жизни происходит что-то приятное (приятное на базовом, бессознательном уровне), связанное с предыдущими решениями планировщика, бюджет пополняется. Если в бюджете нет средств, вы "выгорели", у вас "не хватает силы воли". Важная часть мысли состоит в том, что "приятное" определяется бессознательно, "системой 1". Например, вы очень любите мороженое; съесть мороженое и заработать $1000 могут оказаться одинаково ценными пополнениями бессознательного бюджета, хотя объективно первое примерно в тысячу раз дешевле. Это позволяет управлять "бюджетом" на сознательном уровне, решая оптимизационную задачу, и помогать другим в том же. Например, взрослые люди, как правило, недохвалены: если они делают свою работу профессионально, затратив на это немало усилий, в том числе и волевых, то это "само собой разумеется".

ответить
3

Очередная наша задача - 2471. Minimum Number of Operations to Sort a Binary Tree by Level

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

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

🧠 Идея

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

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

  1. Сбор уровней:
    • Используем std::iter::successors для выполнения обхода дерева по уровням.
    • На каждом шаге собираем значения текущего уровня и формируем следующий уровень из дочерних узлов.
  2. Минимальные перестановки:
    • Для каждого уровня создаем массив индексов, отсортированный по значениям.
    • Используя алгоритм обнаружения циклов, подсчитываем минимальное количество операций для приведения массива к упорядоченному состоянию.

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

ответить
3

Ссылка на задачу — 2467. Most Profitable Path in a Tree.

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

Дано неориентированное корневое дерево с n узлами (нумерованными от 0 до n-1).

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

💭 Идея

Вместо раздельного запуска BFS для поиска пути Боба и последующего прохода динамического программирования по узлам дерева, мы решим задачу одним рекурсивным DFS-проходом.

Для каждого узла будем вычислять:

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

ответить
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 согласных и присутствуют все гласные) подсчитывается количество допустимых подстрок.

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

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

ответить
3

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

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

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

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

💡 Идея

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

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

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

ответить
3

Следующая задача 407. Trapping Rain Water II даёт возможность потренировать пространственное воображение (по крайней мере на этапе выбора адекватного для её решения алгоритма).

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

Дана 3D-сетка, представляющая высоты ячеек. Необходимо вычислить объем воды, который можно удержать после дождя. Вода может заполнять только области, окруженные ячейками с большей высотой.

example-3d-grid

💡 Идея

Мы рассматриваем каждую ячейку как часть сетки, где вода может стекать только в соседние ячейки с меньшей или равной высотой. Используя структуру данных непересекающихся множеств (Disjoint-Set или Union-Find), мы группируем соединённые ячейки и отслеживаем их связь с границами, чтобы определить, какие ячейки могут удерживать воду.

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

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

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

ответить

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