Java Algorithms
111 subscribers
625 photos
623 links
Добро пожаловать💡

Канал для всех, кто ищет качественные решения и объяснения задач на Java

Roadmap по каналу:
https://t.me/algoroadmap/2
Download Telegram
🟡Medium
974. Subarray Sums Divisible by K

Company: 🚖📱🏢

📝Дан массив целых чисел nums и целое число k, вернуть количество непустых подмассивов, сумма которых делится на k

💡: cчитайте остатки от деления префиксных сумм на k

#leetcode974 | #medium #prefixsum
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 974

Time: O(n)
Space: O(k)

💡 Идея
🟦используя массив префиксных сумм prefix, подходящий остаток от деления суммы подмассива от i до j равен (prefix[j] – prefix[i]) % k = 0, что можно записать как prefix[j] % k = prefix[i] % k, то есть нужно найти, сколько раз встречались одинаковые остатки от деления префиксных сумм на k

🟦инициализируем переменные для результата и префиксной суммы и массив частот остатков mod размером k

🟦проходим по заданному массиву:
вычисляем текущий остаток от деления префиксной суммы на k: prefix = (prefix + num % k + k) % k, где +k необходимо, чтобы обработать отрицательные значения

добавляем к результату количество полученного остатка из массива mod, а затем увеличиваем его частоту для следующих проверок

👩‍💻 Java Algo | #solution974
Please open Telegram to view this post
VIEW IN TELEGRAM
🟡Medium
2270. Number of Ways to Split Array

Company: 🏢📱📱

📝Дан целочисленный массив, верните количество допустимых разделений.

Допустимое разделение — сумма элементов от начала массива до индекса i больше или равна сумме элементов от i + 1 до конца, при этом правая часть не должна быть пустой

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

#leetcode2270 | #medium #prefixsum
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 2270

Time: O(n)
Space: O(1)

💡 Идея
чтобы не вычислять префиксную сумму отдельно, мы можем напрямую отслеживать левую и правую суммы, проходя по массиву

инициализируем три переменные: leftSum для суммы элементов слева, rightSum для суммы элементов справа и count для подсчета разделений

в начале leftSum равен 0, а rightSum общей сумме массива, поскольку слева нет элементов, а справа находится весь массив

теперь, каждый раз, когда мы рассматриваем новую позицию разделения, проходя по массиву, текущий элемент перемещается с правой стороны на левую:

обновляем leftSum, добавляя к нему текущий элемент
обновляем rightSum, вычитая из него текущий элемент
если leftSum больше или равно rightSum, то разделение допустимо, и мы увеличиваем count

👩‍💻 Java Algo | #solution2270
Please open Telegram to view this post
VIEW IN TELEGRAM
🟡Medium
3355. Zero Array Transformation I

Company: 🔍

📝Дан целочисленный массив nums и двумерный массив запросов queries, где queries[i] = [li, ri].

Для каждого queries[i] уменьшите все элементы подмассива в диапазоне [li, ri] на 1, при этом элемент не может стать меньше нуля.

Верните true, если после обработки всех запросов все элементы в массиве будут равны 0

💡: для каждого запроса обозначайте начало диапазона и его конец в отдельном массиве

#leetcode3355 | #medium #prefixsum
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 3355

Time: O(n + m)
Space: O(n)

💡 Идея
инициализируем массив prefixMinus для обозначения границ запросов и проходим по всем запросам, отмечая в этом массиве начало диапазона и его конец:

уменьшаем значением по индексу начала, чтобы обозначить, что начался диапазон, на котором будет уменьшение всех последующих элементов
увеличиваем значение по индексу конца + 1, чтобы обозначить, что диапазон закончился и нужно прекратить уменьшение на 1 для следующих элементов

далее проходим по исходному массиву и накапливаем общий минус для текущей позиции, добавляя значения из массива prefixMinus

для каждой позиции проверяем — хватило ли количество диапазонов, которые покрыли данный элемент, чтобы он стал меньше или равен 0 (к текущему элементу добавляем текущий общий минус), если нет — сразу возвращаем false

в конце возвращаем true, так как весь массив пройден и нужное условие выполнилось

👩‍💻 Java Algo | #solution3355
Please open Telegram to view this post
VIEW IN TELEGRAM
🟡Medium
3026. Maximum Good Subarray Sum

Company: 📱🔍

📝Дан массив nums и положительное целое число k. Подмассив называется хорошим, если абсолютная разность между его первым и последним элементом точно равна k.

Верните максимальную сумму хорошего подмассива

💡: используйте HashMap для сохранения элементов и префиксных сумм

#leetcode3026 | #medium #prefixsum
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 3026

Time: O(n)
Space: O(n)

💡 Идея
🟦инициализируем HashMap, в котором будем хранить элементы и префиксные суммы, которые соответствуют их позициям

🟦проходим по массиву, накапливаем текущую сумму и для каждого элемента проверяем, содержится ли в HashMap значение +k или -k от него

🟦если содержится, считаем максимальный результат, как текущая сумма минус сумма из HashMap

🟦кладем в HashMap пару, где:
ключ: текущий элемент
значение: текущая сумма минус текущий элемент, так как при подсчете суммы подмассива, нам необходимо минусовать сумму слева от его начала

🟦при этом кладем в HashMap текущий элемент, только если его там нет или, если префиксная сумма для данного элемента больше текущей

👩‍💻 Java Algo | #solution3026
Please open Telegram to view this post
VIEW IN TELEGRAM
🔴Hard
798. Smallest Rotation with Highest Score

📝Вам дан массив nums, вы можете повернуть его на целое число k влево. После этого элементы, которые меньше или равны своему индексу, оцениваются в один балл.

Верните число k, которое соответствует наивысшему результату, который можно получить после применения поворота. Если есть несколько ответов, верните наименьшее k

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

#leetcode798 | #hard #prefixsum
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 798

Time: O(n)
Space: O(n)

💡 Идея
🟦создаем массив diff[] размером n, который будет хранить изменения количества баллов при каждом сдвиге

🟦далее проходим по массиву и для каждого элемента рассчитываем, при каком сдвиге данный элемент перестанет давать баллы: k = (i - nums[i] + 1 + n) % n, а затем уменьшаем diff[k] на 1, чтобы учесть, что при таком сдвиге баллы уменьшаются

🟦теперь будем накапливать изменения для каждого сдвига от 1 до n, проходя по массиву diff и суммируя их, при этом учитываем, что каждый новый элемент дает +1 балл, потому что в конец массива попадает новый элемент, который точно дает баллы, так как элементы массива по условию от 0 до n

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

Почему k вычисляется именно так?
i: исходная позиция элемента
- nums[i]: смещаемся назад настолько, насколько велик сам элемент
+ 1: смещаемся еще на одну позицию, чтобы теперь элемент не давал баллы
+ n: гарантируем, что выражение не будет отрицательным
% n: берем по модулю, чтобы остаться в пределах массива

Почему изменения для каждого сдвига суммируются?
вычисляя k, мы определяем самую правую позицию, в которой данный элемент не приносит баллы, соответственно при большем сдвиге он сдвигается левее, где также не будет приносить баллы, поэтому мы последовательно суммируем изменения для каждого сдвига. При этом мы учитываем, что массив цикличный, на каждом шаге добавляя в cur +1 для элемента, который перешел в конец массива


👩‍💻 Java Algo | #solution798
Please open Telegram to view this post
VIEW IN TELEGRAM
➡️ Стартуем тему скользящего окна

💡 Идея

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

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

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

#slidingwindow
Please open Telegram to view this post
VIEW IN TELEGRAM
🟢Easy
1652. Defuse the Bomb

Company: 🏢📱📱

📝Дан массив code и целое число k.

Необходимо заменить каждый элемент по следующим правилам:
если k > 0, замените элемент суммой следующих k чисел
если k < 0, замените элемент суммой предыдущих k чисел
если k == 0, замените элемент на 0

Массив code является круговым, поэтому следующим элементом code[n-1] является code[0], а предыдущим элементом code[0] является code[n-1].

Верните полученный массив

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

#leetcode1652 | #easy #slidingwindow
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 1652

Time: O(n)
Space: O(n)

💡 Идея
🟦инициализируем массив для записи результата размером исходного (n) и сразу возвращаем его, если k == 0

🟦инициализируем два указателя: на начало окна start = 1 и конец end = k, но если k < 0, меняем позиции на start = n - |k| и end = n - 1, то есть устанавливая окно перед нулевым элементом

🟦далее считаем сумму в полученном окне, чтобы затем эффективно считать остальные

🟦проходим по исходному массиву, записываем в результат текущую сумму и формируем новую для следующего элемента:

из текущей суммы вычитаем элемент на позиции старта окна (start % n) и добавляем элемент следующий после конца ((end + 1) % n), то есть считаем сумму для следующего окна, меняя только границы, при этом все содержимое между остается неизменным, поэтому мы получаем ее правильно

затем увеличиваем указатели start и end, фактически передвигая окно на следующую позицию


🟦в конце возвращаем полученный массив c результатом

👩‍💻 Java Algo | #solution1652
Please open Telegram to view this post
VIEW IN TELEGRAM
🟢Easy
2379. Minimum Recolors to Get K Consecutive Black Blocks

Company: 🔍📱💻

📝Дана строка, которая содержит символы 'W' и 'B', представляющие белый и черный цвета соответственно. Также дано целое число k— желаемое количество последовательных черных блоков.

За одну операцию вы можете перекрасить белый блок в черный.

Верните минимальное количество операций, необходимое для того, чтобы было хотя бы одно вхождение последовательных k черных блоков

💡: найдите минимальное количество белых блоков в окне

#leetcode2379 | #easy #slidingwindow
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 2379

Time: O(n)
Space: O(1)

💡 Идея
🟦чтобы найти минимальное количество операций, будем искать минимальное количество белых блоков в окне длиной k, вычитая из него количество черных блоков

🟦проходим по строке и увеличиваем счетчик, если текущий символ 'B'

🟦как только, индекс стал больше или равен k, значит мы уже вышли за пределы окна и нужно удалить элемент слева: уменьшаем счетчик, если символ i - k = 'B'

🟦на каждом шаге проверяем минимальное количество белых блоков, как длину окна (k) минус количество черных блоков

👩‍💻 Java Algo | #solution2379
Please open Telegram to view this post
VIEW IN TELEGRAM
🟡Medium
2516. Take K of Each Character From Left and Right

Company: 🔍📱🏢

📝Дана строка s, состоящая из символов 'a', 'b' и 'c', и целое число k. Каждую минуту вы можете взять либо самый левый символ s, либо самый правый символ s.

Верните минимальное количество минут, необходимое для того, чтобы взять не меньше k каждого символа или -1, если это невозможно

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

#leetcode2516 | #medium #slidingwindow
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 2516

Time: O(n)
Space: O(1)

💡 Идея
🟦для решения будем искать самое большое окно из символов такое, что в оставшейся части строки (слева и справа) будут символы, которые удовлетворяют условию по количеству, а затем вычтем его из длины строки
🟦инициализируем массив count размером 3 для подсчета частоты каждого символа и заполняем его, проходя по исходной строке

🟦сразу возвращаем -1, если любой из символов встречается меньше k раз

🟦далее инициализируем массив window для подсчета символов в текущем окне и проходим по исходной строке правым указателем:

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

🟦в конце возвращаем результат: длина строки минус максимальная длина окна

👩‍💻 Java Algo | #solution2516
Please open Telegram to view this post
VIEW IN TELEGRAM
🟡Medium
2461. Maximum Sum of Distinct Subarrays With Length K

Company: 📱📱🏢

📝Дан массив целых чисел nums и целое число k.

Найдите максимальную сумму подмассива длиной k, в котором все элементы различны

💡: сохраняйте в HashMap позиции элементов для исключения дубликатов в окне

#leetcode2461 | #medium #slidingwindow
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 2461

Time: O(n)
Space: O(n)

💡 Идея
🟦инициализируем HashMap, в котором будем хранить позиции элементов, чтобы затем использовать их для исключения дубликатов из окна

🟦проходим по массиву правым указателем и на каждом шаге:
считаем текущую сумму

берем из HashMap последнюю позицию текущего элемента lastPos, если он встречался или -1, если нет

передвигаем левый указатель, вычитая из суммы элементы под ним, пока выполняется одно из условий:
он меньше или равен lastPos (то есть исключаем дубликат из окна)
размер окна превышает k

кладем в HashMap текущий элемент и его позицию и считаем максимальный результат, если размер текущего окна равен k

👩‍💻 Java Algo | #solution2461
Please open Telegram to view this post
VIEW IN TELEGRAM
🟡Medium
2134. Minimum Swaps to Group All 1's Together II

Company: 📱🔍🅰️

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

💡: найдите минимальное кол-во нулей в окне размером общего кол-ва единиц

#leetcode2134 | #medium #slidingwindow
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 2134

Time: O(n)
Space: O(1)

💡 Идея
🟦поскольку сгруппировать единицы можно в любом месте, нужно найти такое окно размером общего количества единиц, в котором будет меньше всего позиций для перестановок, то есть нулей


🟦посчитаем общее кол-во единиц в переменной total и проходим до данного значения правым указателем, подсчитывая текущее кол-во единиц (формируем начальное окно)

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

вычитаем из текущего кол-ва единиц элемент под левым указателем и добавляем элемент под правым

считаем минимальное кол-во нулей в окне, вычитая из общего кол-ва единиц текущее, и передвигаем указатели

👩‍💻 Java Algo | #solution2134
Please open Telegram to view this post
VIEW IN TELEGRAM