Java | LeetCode
6.45K subscribers
222 photos
1.47K links
Сайт: https://easyoffer.ru/
Все каналы: t.me/+xGeAw6ckJ4liYzQy

Контакт для рекламы: @sendme_ads
Download Telegram
Задача: 1031. Maximum Sum of Two Non-Overlapping Subarrays
Сложность: medium

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

Пример:
Input: nums = [0,6,5,2,2,5,1,9,4], firstLen = 1, secondLen = 2
Output: 20


👨‍💻 Алгоритм:

1⃣Предварительные вычисления:
Вычислите сумму всех подмассивов длины firstLen и secondLen и сохраните их в списках.

2⃣Поиск максимальной суммы:
Переберите все возможные позиции для подмассива длины firstLen и для каждого такого подмассива найдите максимальную сумму для подмассива длины secondLen, который не пересекается с текущим подмассивом длины firstLen.

3⃣Сравнение двух случаев:
Рассмотрите оба случая: подмассив длины firstLen до подмассива длины secondLen и подмассив длины secondLen до подмассива длины firstLen. Найдите максимальную сумму для каждого случая.

😎 Решение:
public class Solution {
public int maxSumTwoNoOverlap(int[] nums, int firstLen, int secondLen) {
return Math.max(maxSumNonOverlap(nums, firstLen, secondLen), maxSumNonOverlap(reverse(nums), secondLen, firstLen));
}

private int maxSumNonOverlap(int[] nums, int firstLen, int secondLen) {
int n = nums.length;
int[] prefix = new int[n + 1];
for (int i = 0; i < n; ++i) {
prefix[i + 1] = prefix[i] + nums[i];
}

int[] maxFirst = new int[n];
for (int i = firstLen - 1; i < n; ++i) {
maxFirst[i] = Math.max((i > 0 ? maxFirst[i - 1] : 0), prefix[i + 1] - prefix[i + 1 - firstLen]);
}

int[] maxSecond = new int[n];
for (int i = secondLen - 1; i < n; ++i) {
maxSecond[i] = Math.max((i > 0 ? maxSecond[i - 1] : 0), prefix[i + 1] - prefix[i + 1 - secondLen]);
}

int maxSum = 0;
for (int i = firstLen + secondLen - 1; i < n; ++i) {
maxSum = Math.max(maxSum, maxFirst[i - secondLen] + (prefix[i + 1] - prefix[i + 1 - secondLen]));
}

return maxSum;
}

private int[] reverse(int[] nums) {
int n = nums.length;
int[] reversed = new int[n];
for (int i = 0; i < n; ++i) {
reversed[i] = nums[n - i - 1];
}
return reversed;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 1242. Web Crawler Multithreaded
Сложность: medium

Учитывая URL startUrl и интерфейс HtmlParser, реализуйте многопоточный веб-краулер, который будет просматривать все ссылки, находящиеся под тем же именем хоста, что и startUrl. Верните все URL, полученные вашим веб-краулером, в любом порядке.

Ваш краулер должен: Начинать со страницы: startUrl Вызывать HtmlParser.getUrls(url), чтобы получить все URL с веб-страницы данного URL. Не просматривать одну и ту же ссылку дважды. Исследовать только те ссылки, которые находятся под тем же именем хоста, что и startUrl.

Пример:
Input:
urls = [
"http://news.yahoo.com",
"http://news.yahoo.com/news",
"http://news.yahoo.com/news/topics/",
"http://news.google.com",
"http://news.yahoo.com/us"
]
edges = [[2,0],[2,1],[3,2],[3,1],[0,4]]
startUrl = "http://news.yahoo.com/news/topics/"
Output: [
"http://news.yahoo.com",
"http://news.yahoo.com/news",
"http://news.yahoo.com/news/topics/",
"http://news.yahoo.com/us"
]


👨‍💻 Алгоритм:

1⃣Извлечь имя хоста из startUrl.
Использовать многопоточность для обработки URL-адресов.

2⃣Хранить посещенные URL-адреса, чтобы избежать повторного посещения.

3⃣Использовать HtmlParser для получения URL-адресов с веб-страниц.

😎 Решение:
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;

class HtmlParser {
public List<String> getUrls(String url) {
return new ArrayList<>();
}
}

public class Solution {
public List<String> crawl(String startUrl, HtmlParser htmlParser) {
String hostname = extractHostname(startUrl);
Set<String> visited = ConcurrentHashMap.newKeySet();
ExecutorService executor = Executors.newFixedThreadPool(10);
Queue<Future<?>> futures = new ConcurrentLinkedQueue<>();

visited.add(startUrl);
futures.add(executor.submit(() -> visit(startUrl, htmlParser, hostname, visited, futures, executor)));

while (!futures.isEmpty()) {
try {
futures.poll().get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}

executor.shutdown();
return new ArrayList<>(visited);
}

private void visit(String url, HtmlParser htmlParser, String hostname, Set<String> visited, Queue<Future<?>> futures, ExecutorService executor) {
for (String nextUrl : htmlParser.getUrls(url)) {
if (extractHostname(nextUrl).equals(hostname) && visited.add(nextUrl)) {
futures.add(executor.submit(() -> visit(nextUrl, htmlParser, hostname, visited, futures, executor)));
}
}
}

private String extractHostname(String url) {
try {
URL u = new URL(url);
return u.getHost();
} catch (MalformedURLException e) {
e.printStackTrace();
return "";
}
}
}


Ставь 👍 и забирай 📚 Базу знаний
👍1
Задача: 657. Robot Return to Origin
Сложность: easy

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

Вам дана строка moves, представляющая последовательность движений робота, где moves[i] представляет его i-ое движение. Допустимые движения: 'R' (вправо), 'L' (влево), 'U' (вверх) и 'D' (вниз).

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

Примечание: направление, в котором "смотрит" робот, не имеет значения. 'R' всегда будет перемещать робота на один шаг вправо, 'L' всегда будет перемещать его на один шаг влево и т.д. Также предполагается, что величина перемещения робота одинакова для каждого хода.

Пример:
Input: moves = "UD"
Output: true


👨‍💻 Алгоритм:

1⃣Инициализация координат:
Начните с координат (0, 0).

2⃣Обработка движений:
Пройдите по строке moves и обновляйте координаты в зависимости от движения:
'R' увеличивает координату x на 1.
'L' уменьшает координату x на 1.
'U' увеличивает координату y на 1.
'D' уменьшает координату y на 1.

3⃣Проверка конечных координат:
Если после всех движений координаты снова равны (0, 0), верните true. В противном случае, верните false.

😎 Решение:
public class Solution {
public boolean judgeCircle(String moves) {
int x = 0, y = 0;
for (char move : moves.toCharArray()) {
switch (move) {
case 'R': x++; break;
case 'L': x--; break;
case 'U': y++; break;
case 'D': y--; break;
}
}
return x == 0 && y == 0;
}
}


Ставь 👍 и забирай 📚 Базу знаний
👍2
Задача: 171. Excel Sheet Column Number
Сложность: easy

Дана строка columnTitle, представляющая название столбца, как это отображается в Excel. Вернуть соответствующий номер столбца.

Пример:
Input: columnTitle = "A"
Output: 1


👨‍💻 Алгоритм:

1⃣Создайте отображение букв алфавита и их соответствующих значений (начиная с 1).

2⃣Инициализируйте переменную-аккумулятор result.

3⃣Начиная справа налево, вычислите значение символа в
зависимости от его позиции и добавьте его к result.

😎 Решение:
class Solution {
public int titleToNumber(String s) {
int result = 0;

Map<Character, Integer> alpha_map = new HashMap<>();
for (int i = 0; i < 26; i++) {
int c = i + 65;
alpha_map.put((char) c, i + 1);
}

int n = s.length();
for (int i = 0; i < n; i++) {
char cur_char = s.charAt(n - 1 - i);
result += alpha_map.get(cur_char) * Math.pow(26, i);
}
return result;
}
}


Ставь 👍 и забирай 📚 Базу знаний
👍1
Задача: 442. Find All Duplicates in an Array
Сложность: medium

Дан целочисленный массив nums длины n, где все целые числа nums находятся в диапазоне [1, n], и каждое число появляется один или два раза. Верните массив всех чисел, которые появляются дважды.

Вы должны написать алгоритм, который работает за время O(n) и использует только постоянное дополнительное пространство.

Пример:
Input: nums = [4,3,2,7,8,2,3,1]
Output: [2,3]


👨‍💻 Алгоритм:

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

2⃣Поскольку элемент может появляться только один или два раза, нам не нужно беспокоиться о получении дубликатов элементов, которые появляются дважды: Случай I: Если элемент встречается в массиве только один раз, при поиске его в остальной части массива ничего не найдется. Случай II: Если элемент встречается дважды, вы найдете второе вхождение элемента в оставшейся части массива. Когда вы наткнетесь на второе вхождение в более поздней итерации, это будет аналогично случаю I (поскольку больше вхождений этого элемента в оставшейся части массива не будет).

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

😎 Решение:
class Solution {
public List<Integer> findDuplicates(int[] nums) {
List<Integer> ans = new ArrayList<>();

for (int i = 0; i < nums.length; i++)
for (int j = i + 1; j < nums.length; j++) {
if (nums[j] == nums[i]) {
ans.add(nums[i]);
break;
}
}

return ans;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 409. Longest Palindrome
Сложность: easy

Если задана строка s, состоящая из строчных или прописных букв, верните длину самого длинного палиндрома, который можно построить из этих букв. Буквы чувствительны к регистру, например, "Aa" не считается палиндромом.

Пример:
Input: s = "abccccdd"
Output: 7


👨‍💻 Алгоритм:

1⃣Создайте словарь для подсчета количества каждого символа в строке.

2⃣Пройдитесь по словарю и добавьте четное количество каждого символа к длине палиндрома. Если встречается нечетное количество символа, добавьте (count - 1) к длине палиндрома.

3⃣Если есть хотя бы один символ с нечетным количеством, добавьте 1 к длине палиндрома для центрального символа.

😎 Решение:
import java.util.HashMap;
import java.util.Map;

public class Solution {
public int longestPalindrome(String s) {
Map<Character, Integer> charCount = new HashMap<>();
for (char c : s.toCharArray()) {
charCount.put(c, charCount.getOrDefault(c, 0) + 1);
}
int length = 0;
boolean oddFound = false;
for (int count : charCount.values()) {
if (count % 2 == 0) {
length += count;
} else {
length += count - 1;
oddFound = true;
}
}
return oddFound ? length + 1 : length;
}
}


Ставь 👍 и забирай 📚 Базу знаний
👍1
Задача: 1354. Construct Target Array With Multiple Sums
Сложность: hard

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

Пусть x будет суммой всех элементов, находящихся в вашем массиве.
Выберите индекс i так, чтобы 0 <= i < n, и установите значение arr в индексе i равным x.
Вы можете повторять эту процедуру столько раз, сколько потребуется.
Верните true, если возможно построить массив target из arr, в противном случае верните false.

Пример:
Input: target = [8,5]
Output: true


👨‍💻 Алгоритм:

1⃣Использование максимальной кучи (Max Heap) для отслеживания максимальных значений в target:
Сначала необходимо инициализировать кучу с максимальным приоритетом, чтобы всегда иметь доступ к наибольшему элементу в массиве target.
Вычислить сумму всех элементов в target и сохранить ее.

2⃣Повторение процесса переворота:
Извлечь наибольшее значение из кучи. Вычесть это значение из общей суммы.
Проверить несколько условий:
Если извлеченное значение равно 1 или общая сумма равна 1, вернуть true.
Если извлеченное значение меньше общей суммы, общая сумма равна 0, или извлеченное значение делится на общую сумму без остатка, вернуть false.
Остаток от деления наибольшего значения на общую сумму является новым значением, которое нужно вставить обратно в кучу. Обновить общую сумму.

3⃣Повторение цикла до достижения результата:
Повторять шаг 2 до тех пор, пока не будут выполнены условия выхода из цикла (возврат true или false).

😎 Решение:
import java.util.PriorityQueue;

public class Solution {
public boolean isPossible(int[] target) {
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a);
long total = 0;
for (int num : target) {
total += num;
pq.add(num);
}

while (pq.peek() > 1) {
int maxVal = pq.poll();
total -= maxVal;
if (maxVal < total || total == 0 || maxVal % total == 0) return false;
pq.add(maxVal % total);
total += pq.peek();
}
return true;
}
}


Ставь 👍 и забирай 📚 Базу знаний
#medium
Задача: 714. Best Time to Buy and Sell Stock with Transaction Fee
Сложность: medium

Вам дан массив prices, где prices[i] - это цена данной акции в i-й день, и целое число fee, представляющее собой комиссию за сделку. Найдите максимальную прибыль, которую вы можете получить. Вы можете совершить сколько угодно сделок, но за каждую сделку вам придется заплатить комиссию. Примечание: Вы не можете совершать несколько сделок одновременно (то есть вы должны продать акции, прежде чем купить их снова). Комиссия за сделку взимается только один раз за каждую покупку и продажу акций.

Пример:
Input: prices = [1,3,2,8,4,9], fee = 2
Output: 8


👨‍💻 Алгоритм:

1⃣Инициализируйте две переменные: cash, представляющую максимальную прибыль без наличия акций, и hold, представляющую максимальную прибыль с наличием акций.

2⃣Пройдите по каждому элементу массива prices и обновите значения cash и hold, используя текущую цену и комиссию.

3⃣Верните значение cash, которое будет максимальной прибылью без наличия акций.

😎 Решение:
public class Solution {
public int maxProfit(int[] prices, int fee) {
int cash = 0, hold = -prices[0];
for (int price : prices) {
cash = Math.max(cash, hold + price - fee);
hold = Math.max(hold, cash - price);
}
return cash;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 815. Bus Routes
Сложность: hard

Дан массив routes, представляющий автобусные маршруты, где routes[i] - это автобусный маршрут, который i-й автобус повторяет бесконечно.

Например, если routes[0] = [1, 5, 7], это означает, что 0-й автобус путешествует в последовательности 1 -> 5 -> 7 -> 1 -> 5 -> 7 -> 1 -> ... бесконечно.
Вы начинаете на автобусной остановке source (вы изначально не находитесь в автобусе) и хотите добраться до автобусной остановки target. Перемещаться между автобусными остановками можно только на автобусах.

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

Пример:
Input: routes = [[1,2,7],[3,6,7]], source = 1, target = 6
Output: 2
Explanation: The best strategy is take the first bus to the bus stop 7, then take the second bus to the bus stop 6.


👨‍💻 Алгоритм:

1⃣Верните 0, если source и target совпадают. Инициализируйте пустую карту adjList, чтобы хранить ребра, где ключ - это автобусная остановка, а значение - список целых чисел, обозначающих индексы маршрутов, которые имеют эту остановку. Инициализируйте пустую очередь q и неупорядоченное множество vis, чтобы отслеживать посещенные маршруты. Вставьте начальные маршруты в очередь q и отметьте их посещенными в vis.

2⃣Итерация по очереди, пока она не пуста: извлеките маршрут из очереди, итерируйтесь по остановкам в маршруте. Если остановка равна target, верните busCount. В противном случае, итерируйтесь по маршрутам для этой остановки в карте adjList, добавьте непосещенные маршруты в очередь и отметьте их посещенными.

3⃣Верните -1 после завершения обхода в ширину (BFS).

😎 Решение:
class Solution {
public int numBusesToDestination(int[][] routes, int source, int target) {
if (source == target) return 0;

Map<Integer, List<Integer>> adjList = new HashMap<>();
for (int route = 0; route < routes.length; route++) {
for (int stop : routes[route]) {
adjList.computeIfAbsent(stop, k -> new ArrayList<>()).add(route);
}
}

Queue<Integer> q = new LinkedList<>();
Set<Integer> vis = new HashSet<>();
for (int route : adjList.getOrDefault(source, Collections.emptyList())) {
q.add(route);
vis.add(route);
}

int busCount = 1;
while (!q.isEmpty()) {
int size = q.size();

for (int i = 0; i < size; i++) {
int route = q.poll();

for (int stop : routes[route]) {
if (stop == target) {
return busCount;
}

for (int nextRoute : adjList.getOrDefault(stop, Collections.emptyList())) {
if (!vis.contains(nextRoute)) {
vis.add(nextRoute);
q.add(nextRoute);
}
}
}
}
busCount++;
}
return -1;
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 730. Count Different Palindromic Subsequences
Сложность: hard

Поскольку ответ может быть очень большим, верните его по модулю 109 + 7. Подпоследовательность строки получается путем удаления из нее нуля или более символов. Последовательность является палиндромной, если она равна последовательности, обращенной назад. Две последовательности a1, a2, ... и b1, b2, ... различны, если существует некоторое i, для которого ai != bi.

Пример:
Input: s = "bccb"
Output: 6


👨‍💻 Алгоритм:

1⃣Используйте динамическое программирование для подсчета количества палиндромных подпоследовательностей.

2⃣Введите двумерный массив dp, где dp[i][j] представляет количество палиндромных подпоследовательностей в подстроке от i до j.

3⃣Итерируйте по длине подстрок от 1 до длины строки и обновляйте значения в dp на основе состояния предыдущих подстрок.

😎 Решение:
public class Solution {
public int countPalindromicSubsequences(String s) {
int MOD = 1000000007;
int n = s.length();
int[][] dp = new int[n][n];

for (int i = 0; i < n; i++) {
dp[i][i] = 1;
}

for (int length = 2; length <= n; length++) {
for (int i = 0; i <= n - length; i++) {
int j = i + length - 1;
if (s.charAt(i) == s.charAt(j)) {
int l = i + 1, r = j - 1;
while (l <= r && s.charAt(l) != s.charAt(i)) l++;
while (l <= r && s.charAt(r) != s.charAt(j)) r--;
if (l > r) {
dp[i][j] = dp[i + 1][j - 1] * 2 + 2;
} else if (l == r) {
dp[i][j] = dp[i + 1][j - 1] * 2 + 1;
} else {
dp[i][j] = dp[i + 1][j - 1] * 2 - dp[l + 1][r - 1];
}
} else {
dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1];
}
dp[i][j] = (dp[i][j] + MOD) % MOD;
}
}

return dp[0][n - 1];
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 1054. Distant Barcodes
Сложность: medium

На складе имеется ряд штрих-кодов, где i-й штрих-код - barcodes[i]. Переставьте штрих-коды так, чтобы два соседних штрих-кода не были одинаковыми. Вы можете вернуть любой ответ, и гарантируется, что ответ существует.

Пример:
Input: barcodes = [1,1,1,2,2,2]
Output: [2,1,2,1,2,1]


👨‍💻 Алгоритм:

1⃣Подсчитай частоту каждого штрих-кода.
Помести все штрих-коды в максимальную кучу на основе их частоты.

2⃣Извлекай штрих-коды из кучи, чередуя их, чтобы два соседних штрих-кода не были одинаковыми.

3⃣Если куча становится пустой, помести временно сохранённый штрих-код обратно в кучу.

😎 Решение:
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

public class Solution {
public int[] rearrangeBarcodes(int[] barcodes) {
Map<Integer, Integer> count = new HashMap<>();
for (int barcode : barcodes) {
count.put(barcode, count.getOrDefault(barcode, 0) + 1);
}

PriorityQueue<int[]> maxHeap = new PriorityQueue<>((a, b) -> b[0] - a[0]);
for (Map.Entry<Integer, Integer> entry : count.entrySet()) {
maxHeap.add(new int[]{entry.getValue(), entry.getKey()});
}

int prevFreq = 0, prevBarcode = -1;
int[] result = new int[barcodes.length];
int index = 0;

while (!maxHeap.isEmpty()) {
int[] entry = maxHeap.poll();
int freq = entry[0], barcode = entry[1];
result[index++] = barcode;
if (prevFreq > 0) {
maxHeap.add(new int[]{prevFreq, prevBarcode});
}
prevFreq = freq - 1;
prevBarcode = barcode;
}

return result;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 1135. Connecting Cities With Minimum Cost
Сложность: medium

Есть n городов, пронумерованных от 1 до n. Вам даны целое число n и массив connections, где connections[i] = [xi, yi, costi] указывает, что стоимость соединения города xi и города yi (двунаправленное соединение) равна costi.

Верните минимальную стоимость для соединения всех n городов так, чтобы между каждой парой городов был хотя бы один путь. Если невозможно соединить все n городов, верните -1.

Стоимость - это сумма использованных стоимостей соединений.

Пример:
Input: n = 3, connections = [[1,2,5],[1,3,6],[2,3,1]]
Output: 6
Explanation: Choosing any 2 edges will connect all cities so we choose the minimum 2.


👨‍💻 Алгоритм:

1⃣Сортировка рёбер:
Отсортируйте все соединения (рёбра) в графе по их весам (стоимости) в порядке возрастания.

2⃣Итерация по рёбрам и объединение:
Используйте структуру данных Disjoint Set (Union-Find) для проверки циклов и объединения поддеревьев. Для каждого ребра проверьте, принадлежат ли его концы разным поддеревьям, и если да, объедините их, добавив ребро в минимальное остовное дерево (MST).

3⃣Проверка соединённости:
Подсчитайте количество рёбер в MST. Если оно меньше n-1, верните -1, так как соединить все города невозможно. Иначе верните суммарную стоимость рёбер в MST.

😎 Решение:
class DisjointSet {
private int[] parents;

public void Union(int a, int b) {
int rootA = Find(a);
int rootB = Find(b);
if (rootA == rootB) return;
this.parents[rootB] = rootA;
}

public int Find(int a) {
while (a != this.parents[a]) {
a = this.parents[a];
}
return a;
}

public boolean isInSameGroup(int a, int b) {
return Find(a) == Find(b);
}

public DisjointSet(int N) {
this.parents = new int[N + 1];
for (int i = 1; i <= N; ++i) {
this.parents[i] = i;
}
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 972. Equal Rational Numbers
Сложность: hard

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

Рациональное число может быть представлено с использованием до трех частей: <ЦелаяЧасть>, <НеповторяющаясяЧасть> и <ПовторяющаясяЧасть>. Число будет представлено одним из следующих трех способов:

<ЦелаяЧасть>
Например, 12, 0 и 123.
<ЦелаяЧасть><.><НеповторяющаясяЧасть>
Например, 0.5, 1., 2.12 и 123.0001.
<ЦелаяЧасть><.><НеповторяющаясяЧасть><(><ПовторяющаясяЧасть><)>
Например, 0.1(6), 1.(9), 123.00(1212).
Повторяющаяся часть десятичного разложения обозначается в круглых скобках. Например:

1/6 = 0.16666666... = 0.1(6) = 0.1666(6) = 0.166(66).

Пример:
Input: s = "0.(52)", t = "0.5(25)"
Output: true
Explanation: Because "0.(52)" represents 0.52525252..., and "0.5(25)" represents 0.52525252525..... , the strings represent the same number.


👨‍💻 Алгоритм:

1⃣Преобразование дроби. Определите и изолируйте повторяющуюся часть дроби. Преобразуйте строку, представляющую число, в выражение вида S=x/(10^k-1), где x — повторяющаяся часть, а k — её длина.

2⃣Вычисление геометрической суммы. Преобразуйте повторяющуюся часть в сумму вида S=x*(r/(1-r)), где r = 10^(-k). Найдите значение дроби для повторяющейся части, используя формулу геометрической прогрессии.

3⃣Обработка неповторяющейся части. Определите значение неповторяющейся части дроби как обычное число. Объедините результаты для повторяющейся и неповторяющейся частей для получения итогового значения.

😎 Решение:
class Employee {
public int id;
public int importance;
public List<Integer> subordinates;
}

class Solution {
Map<Integer, Employee> emap;

public int getImportance(List<Employee> employees, int queryid) {
emap = new HashMap<>();
for (Employee e : employees) {
emap.put(e.id, e);
}
return dfs(queryid);
}

public int dfs(int eid) {
Employee employee = emap.get(eid);
int ans = employee.importance;
for (Integer subid : employee.subordinates) {
ans += dfs(subid);
}
return ans;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 868. Binary Gap
Сложность: easy

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

Две единицы считаются соседними, если их разделяют только нули (возможно, никаких нулей нет). Расстояние между двумя единицами — это абсолютная разница между их позициями в битовом представлении. Например, две единицы в "1001" имеют расстояние 3.

Пример:
Input: n = 22
Output: 2
Explanation: 22 in binary is "10110".
The first adjacent pair of 1's is "10110" with a distance of 2.
The second adjacent pair of 1's is "10110" with a distance of 1.
The answer is the largest of these two distances, which is 2.
Note that "10110" is not a valid pair since there is a 1 separating the two 1's underlined.


👨‍💻 Алгоритм:

1⃣Создайте список A индексов i, таких что в двоичном представлении числа n i-й бит установлен в 1.

2⃣Используйте список A, чтобы найти максимальное расстояние между соседними значениями. Для этого пройдите по списку и вычислите разницу между каждым соседним элементом.

3⃣Верните найденное максимальное расстояние.

😎 Решение:
class Solution {
public int binaryGap(int N) {
int[] A = new int[32];
int t = 0;
for (int i = 0; i < 32; ++i)
if (((N >> i) & 1) != 0)
A[t++] = i;

int ans = 0;
for (int i = 0; i < t - 1; ++i)
ans = Math.max(ans, A[i+1] - A[i]);
return ans;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 643. Maximum Average Subarray I
Сложность: easy

Вам дан целочисленный массив nums, состоящий из n элементов, и целое число k. Найдите смежный подмассив, длина которого равна k и который имеет максимальное среднее значение, и верните это значение. Принимается любой ответ с погрешностью вычислений менее 10-5.

Пример:
Input: nums = [1,12,-5,-6,50,3], k = 4
Output: 12.75000


👨‍💻 Алгоритм:

1⃣Инициализация скользящего окна
Вычислите сумму первых k элементов массива nums. Это будет начальное значение максимальной суммы.

2⃣Перемещение окна
Перемещайте окно длиной k по массиву, добавляя следующий элемент и убирая предыдущий, чтобы поддерживать сумму текущего окна.

3⃣Обновление максимальной суммы
На каждом шаге обновляйте максимальную сумму, если текущая сумма больше, и в конце верните среднее значение этой суммы.

😎 Решение:
public class Solution {
public double findMaxAverage(int[] nums, int k) {
int currentSum = 0;
for (int i = 0; i < k; i++) {
currentSum += nums[i];
}
int maxSum = currentSum;

for (int i = k; i < nums.length; i++) {
currentSum += nums[i] - nums[i - k];
maxSum = Math.max(maxSum, currentSum);
}

return (double) maxSum / k;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 1207. Unique Number of Occurrences
Сложность: easy

Дан массив целых чисел arr. Верните true, если количество вхождений каждого значения в массиве уникально, или false в противном случае.

Пример:
Input: arr = [1,2,2,1,1,3]
Output: true
Explanation: The value 1 has 3 occurrences, 2 has 2 and 3 has 1. No two values have the same number of occurrences.


👨‍💻 Алгоритм:

1⃣Сохраните частоты элементов массива arr в хэш-таблице freq.

2⃣Итерируйтесь по хэш-таблице freq и вставьте частоты всех уникальных элементов массива arr в хэш-набор freqSet.

3⃣Верните true, если размер хэш-набора freqSet равен размеру хэш-таблицы freq, иначе верните false.

😎 Решение:
class Solution {
public boolean uniqueOccurrences(int[] arr) {
Map<Integer, Integer> freq = new HashMap<>();
for (int num : arr) {
freq.put(num, freq.getOrDefault(num, 0) + 1);
}

Set<Integer> freqSet = new HashSet<>(freq.values());

return freq.size() == freqSet.size();
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 200. Number of Islands
Сложность: medium

Дана двумерная бинарная сетка размером m x n, представляющая карту из '1' (земля) и '0' (вода). Верните количество островов.

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

Пример:
Input: grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
Output: 1


👨‍💻 Алгоритм:

1⃣Линейно просканируйте двумерную карту, если узел содержит '1', то это корневой узел, который запускает поиск в глубину (DFS).

2⃣Во время выполнения DFS каждый посещённый узел следует установить в '0', чтобы пометить его как посещённый.

3⃣Подсчитайте количество корневых узлов, запускающих DFS. Это количество будет равно количеству островов, так как каждый DFS, начинающийся с какого-либо корня, идентифицирует остров.

😎 Решение:
class Solution {
void dfs(char[][] grid, int r, int c) {
int nr = grid.length;
int nc = grid[0].length;

if (r < 0 || c < 0 || r >= nr || c >= nc || grid[r][c] == '0') {
return;
}

grid[r][c] = '0';
dfs(grid, r - 1, c);
dfs(grid, r + 1, c);
dfs(grid, r, c - 1);
dfs(grid, r, c + 1);
}

public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}

int nr = grid.length;
int nc = grid[0].length;
int num_islands = 0;
for (int r = 0; r < nr; ++r) {
for (int c = 0; c < nc; ++c) {
if (grid[r][c] == '1') {
++num_islands;
dfs(grid, r, c);
}
}
}

return num_islands;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 1353. Maximum Number of Events That Can Be Attended
Сложность: medium

Дан массив событий, где events[i] = [startDayi, endDayi]. Каждое событие i начинается в startDayi и заканчивается в endDayi.

Вы можете посетить событие i в любой день d, где startDayi <= d <= endDayi. Вы можете посещать только одно событие в любой момент времени d.

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

Пример:
Input: events= [[1,2],[2,3],[3,4],[1,2]]
Output: 4


👨‍💻 Алгоритм:

1⃣Сортировка событий по времени завершения:
Сначала отсортируйте массив событий по времени окончания каждого события в порядке возрастания. Это позволит сначала рассматривать события, которые заканчиваются раньше.

2⃣Использование множества для отслеживания посещенных дней:
Создайте множество для хранения дней, в которые уже были посещены события. Это позволит легко проверять, был ли день уже использован для посещения другого события.

3⃣Посещение событий в доступные дни:
Пройдитесь по отсортированному массиву событий. Для каждого события проверьте каждый день от начала события до его окончания и найдите первый доступный день, который еще не был использован. Если такой день найден, добавьте его в множество и увеличьте счетчик посещенных событий.

😎 Решение:
import java.util.*;

public class Solution {
public int maxEvents(int[][] events) {
Arrays.sort(events, Comparator.comparingInt(e -> e[1]));
Set<Integer> visitedDays = new HashSet<>();
int count = 0;

for (int[] event : events) {
for (int day = event[0]; day <= event[1]; day++) {
if (!visitedDays.contains(day)) {
visitedDays.add(day);
count++;
break;
}
}
}
return count;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 1262. Greatest Sum Divisible by Three
Сложность: medium

Если задан целочисленный массив nums, верните максимально возможную сумму элементов массива, которая делится на три.

Пример:
Input: nums = [3,6,5,1,8]
Output: 18


👨‍💻 Алгоритм:

1⃣Найдите сумму всех элементов массива.

2⃣Если сумма делится на 3, то она и есть ответ.

3⃣Если сумма при делении на 3 дает остаток 1, удалите один элемент с остатком 1 или два элемента с остатком 2 (если их сумма равна 2).
Если сумма при делении на 3 дает остаток 2, удалите один элемент с остатком 2 или два элемента с остатком 1 (если их сумма равна 2).

😎 Решение:
import java.util.Arrays;

public class Solution {
public int maxSumDivThree(int[] nums) {
int totalSum = Arrays.stream(nums).sum();
if (totalSum % 3 == 0) {
return totalSum;
}

int mod1Min = Integer.MAX_VALUE;
int mod2Min = Integer.MAX_VALUE;
int[] mod1Min2 = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE};
int[] mod2Min2 = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE};

for (int num : nums) {
if (num % 3 == 1) {
if (num < mod1Min2[1]) {
mod1Min2[1] = num;
Arrays.sort(mod1Min2);
}
} else if (num % 3 == 2) {
if (num < mod2Min2[1]) {
mod2Min2[1] = num;
Arrays.sort(mod2Min2);
}
}
}

int result = 0;
if (totalSum % 3 == 1) {
result = totalSum - mod1Min2[0];
if (mod2Min2[0] != Integer.MAX_VALUE && mod2Min2[1] != Integer.MAX_VALUE) {
result = Math.max(result, totalSum - mod2Min2[0] - mod2Min2[1]);
}
} else if (totalSum % 3 == 2) {
result = totalSum - mod2Min2[0];
if (mod1Min2[0] != Integer.MAX_VALUE && mod1Min2[1] != Integer.MAX_VALUE) {
result = Math.max(result, totalSum - mod1Min2[0] - mod1Min2[1]);
}
}

return result;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 947. Most Stones Removed with Same Row or Column
Сложность: medium

Учитывая массив stones длины n, где stones[i] = [xi, yi] представляет местоположение i-го камня, верните наибольшее возможное количество камней, которые могут быть удалены.

Пример:
Input: stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]
Output: 5


👨‍💻 Алгоритм:

1⃣Представить каждую строку и столбец как узлы в графе.

2⃣Создать связи между узлами для камней, которые находятся в той же строке или столбце.
Использовать алгоритм поиска в глубину (DFS) или объединение-поиска (Union-Find), чтобы найти компоненты связности.

3⃣Количество камней, которые могут быть удалены, это общее количество камней минус количество компонентов связности.

😎 Решение:
import java.util.*;

class Solution {
public int removeStones(int[][] stones) {
Map<Integer, Integer> parent = new HashMap<>();

int find(int x) {
if (!parent.containsKey(x)) {
parent.put(x, x);
}
if (parent.get(x) != x) {
parent.put(x, find(parent.get(x)));
}
return parent.get(x);
}

void union(int x, int y) {
parent.put(find(x), find(y));
}

for (int[] stone : stones) {
union(stone[0], ~stone[1]);
}

Set<Integer> uniqueRoots = new HashSet<>();
for (int key : parent.keySet()) {
uniqueRoots.add(find(key));
}

return stones.length - uniqueRoots.size();
}
}


Ставь 👍 и забирай 📚 Базу знаний
Задача: 836. Rectangle Overlap
Сложность: easy

Прямоугольник, выровненный по осям, представляется в виде списка [x1, y1, x2, y2], где (x1, y1) — координата его нижнего левого угла, а (x2, y2) — координата его верхнего правого угла. Его верхняя и нижняя грани параллельны оси X, а левая и правая грани параллельны оси Y.

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

Даны два выровненных по осям прямоугольника rec1 и rec2, вернуть true, если они перекрываются, в противном случае вернуть false.

Пример:
Input: rec1 = [0,0,2,2], rec2 = [1,1,3,3]
Output: true


👨‍💻 Алгоритм:

1⃣Рассчитайте ширину пересечения: пересечение по оси x положительно, если min(rec1[2], rec2[2]) > max(rec1[0], rec2[0]).

2⃣Рассчитайте высоту пересечения: пересечение по оси y положительно, если min(rec1[3], rec2[3]) > max(rec1[1], rec2[1]).

3⃣Если и ширина, и высота пересечения положительны, прямоугольники перекрываются.

😎 Решение:
class Solution {
public boolean isRectangleOverlap(int[] rec1, int[] rec2) {
return (Math.min(rec1[2], rec2[2]) > Math.max(rec1[0], rec2[0]) &&
Math.min(rec1[3], rec2[3]) > Math.max(rec1[1], rec2[1]));
}
}


Ставь 👍 и забирай 📚 Базу знаний
👍1