Задача: 751. IP to CIDR
Сложность: medium
Дан указатель на начало односвязного списка и два целых числа left и right, где left <= right. Необходимо перевернуть узлы списка, начиная с позиции left и заканчивая позицией right, и вернуть измененный список.
Пример:
👨💻 Алгоритм:
1⃣ Преобразовать начальный IP-адрес в целое число.
2⃣ Пока количество оставшихся IP-адресов n больше нуля: Определить наибольший блок, который начинается с текущего IP-адреса и не превышает количество оставшихся IP-адресов. Добавить этот блок к результату. Увеличить текущий IP-адрес на размер блока. Уменьшить количество оставшихся IP-адресов n.
3⃣ Преобразовать блоки обратно в формат CIDR и вернуть их.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан указатель на начало односвязного списка и два целых числа left и right, где left <= right. Необходимо перевернуть узлы списка, начиная с позиции left и заканчивая позицией right, и вернуть измененный список.
Пример:
Input: ip = "255.0.0.7", n = 10
Output: ["255.0.0.7/32","255.0.0.8/29","255.0.0.16/32"]
public class Solution {
private int IpToInt(string ip) {
var parts = ip.Split('.');
return (int.Parse(parts[0]) << 24) + (int.Parse(parts[1]) << 16) +
(int.Parse(parts[2]) << 8) + int.Parse(parts[3]);
}
private string IntToIp(int num) {
return $"{(num >> 24) & 255}.{(num >> 16) & 255}.{(num >> 8) & 255}.{num & 255}";
}
private string Cidr(string ip, int prefixLength) {
return $"{ip}/{prefixLength}";
}
public List<string> FindCidrBlocks(string startIp, int n) {
int start = IpToInt(startIp);
var result = new List<string>();
while (n > 0) {
int maxSize = 1;
while (maxSize <= start && maxSize <= n) {
maxSize <<= 1;
}
maxSize >>= 1;
while (start % maxSize != 0) {
maxSize >>= 1;
}
result.Add(Cidr(IntToIp(start), 32 - BitCount(maxSize - 1) + 1));
start += maxSize;
n -= maxSize;
}
return result;
}
private int BitCount(int n) {
return (int)Math.Log(n, 2) + 1;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 649. Dota2 Senate
Сложность: medium
В мире Dota2 есть две партии: Radiant и Dire. Сенат Dota2 состоит из сенаторов, представляющих две партии. Теперь сенат хочет принять решение об изменении игры Dota2. Голосование за это изменение проходит в несколько раундов. В каждом раунде каждый сенатор может воспользоваться одним из двух прав: Запретить право одного сенатора: Сенатор может заставить другого сенатора потерять все свои права в этом и всех последующих раундах. Объявить о победе: Если этот сенатор обнаружил, что все сенаторы, у которых еще есть право голоса, принадлежат к одной партии, он может объявить о победе и принять решение об изменении игры. Дана строка senate, представляющая партийную принадлежность каждого сенатора. Символы "R" и "D" обозначают партию Лучезарных и партию Ужасных. Если сенаторов n, то размер данной строки будет равен n. Процедура голосования по кругу начинается от первого сенатора к последнему в заданном порядке. Эта процедура длится до конца голосования. Все сенаторы, потерявшие свои права, будут пропущены во время процедуры. Предположим, что каждый сенатор достаточно умен и будет играть по лучшей стратегии для своей партии. Предскажите, какая партия в итоге объявит о победе и изменит игру в Dota2. На выходе должно получиться "Radiant" или "Dire".
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте две очереди для хранения индексов сенаторов от партий Radiant и Dire.
2⃣ Выполните цикл, пока обе очереди не станут пустыми: Сравните индексы первых сенаторов из обеих очередей. Удалите сенатора с меньшим индексом из очереди и добавьте его с индексом, увеличенным на длину строки. Удалите сенатора с большим индексом из очереди.
3⃣ Если одна из очередей опустела, объявите победу партии, чья очередь еще содержит сенаторов.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
В мире Dota2 есть две партии: Radiant и Dire. Сенат Dota2 состоит из сенаторов, представляющих две партии. Теперь сенат хочет принять решение об изменении игры Dota2. Голосование за это изменение проходит в несколько раундов. В каждом раунде каждый сенатор может воспользоваться одним из двух прав: Запретить право одного сенатора: Сенатор может заставить другого сенатора потерять все свои права в этом и всех последующих раундах. Объявить о победе: Если этот сенатор обнаружил, что все сенаторы, у которых еще есть право голоса, принадлежат к одной партии, он может объявить о победе и принять решение об изменении игры. Дана строка senate, представляющая партийную принадлежность каждого сенатора. Символы "R" и "D" обозначают партию Лучезарных и партию Ужасных. Если сенаторов n, то размер данной строки будет равен n. Процедура голосования по кругу начинается от первого сенатора к последнему в заданном порядке. Эта процедура длится до конца голосования. Все сенаторы, потерявшие свои права, будут пропущены во время процедуры. Предположим, что каждый сенатор достаточно умен и будет играть по лучшей стратегии для своей партии. Предскажите, какая партия в итоге объявит о победе и изменит игру в Dota2. На выходе должно получиться "Radiant" или "Dire".
Пример:
Input: senate = "RD"
Output: "Radiant"
using System;
using System.Collections.Generic;
public class Solution {
public string PredictPartyVictory(string senate) {
Queue<int> radiant = new Queue<int>();
Queue<int> dire = new Queue<int>();
for (int i = 0; i < senate.Length; i++) {
if (senate[i] == 'R') {
radiant.Enqueue(i);
} else {
dire.Enqueue(i);
}
}
while (radiant.Count > 0 && dire.Count > 0) {
int r = radiant.Dequeue();
int d = dire.Dequeue();
if (r < d) {
radiant.Enqueue(r + senate.Length);
} else {
dire.Enqueue(d + senate.Length);
}
}
return radiant.Count > 0 ? "Radiant" : "Dire";
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
Задача: 1021. Remove Outermost Parentheses
Сложность: easy
Например, "", "()", "(" + A + ")" или A + B, где A и B - допустимые строки со скобками, а + означает объединение строк. Все допустимые строки со скобками - "", "()", "(())()" и "(()(())".
Допустимая строка со скобками s является примитивной, если она непустая и не существует способа разбить ее на s = A + B, причем A и B - непустые допустимые строки со скобками. Если дана допустимая строка со скобками s, рассмотрим ее примитивное разложение: s = P1 + P2 + ... + Pk, где Pi - примитивные допустимые строки со скобками. Верните s после удаления крайних скобок из каждой примитивной строки в примитивном разложении s.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация переменных:
Создайте пустую строку для хранения результата.
Используйте счетчик для отслеживания уровня вложенности скобок..
2⃣ Обработка строки:
Итерируйте по каждому символу строки.
Если встречаете (, увеличивайте счетчик уровня вложенности. Если уровень вложенности больше 1, добавьте ( в результат.
Если встречаете ), уменьшайте счетчик уровня вложенности. Если уровень вложенности больше 0 перед уменьшением, добавьте ) в результат.
3⃣ Возврат результата:
Верните результат, содержащий строку без крайних скобок из каждой примитивной строки.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Например, "", "()", "(" + A + ")" или A + B, где A и B - допустимые строки со скобками, а + означает объединение строк. Все допустимые строки со скобками - "", "()", "(())()" и "(()(())".
Допустимая строка со скобками s является примитивной, если она непустая и не существует способа разбить ее на s = A + B, причем A и B - непустые допустимые строки со скобками. Если дана допустимая строка со скобками s, рассмотрим ее примитивное разложение: s = P1 + P2 + ... + Pk, где Pi - примитивные допустимые строки со скобками. Верните s после удаления крайних скобок из каждой примитивной строки в примитивном разложении s.
Пример:
Input: s = "(()())(())"
Output: "()()()"
Создайте пустую строку для хранения результата.
Используйте счетчик для отслеживания уровня вложенности скобок..
Итерируйте по каждому символу строки.
Если встречаете (, увеличивайте счетчик уровня вложенности. Если уровень вложенности больше 1, добавьте ( в результат.
Если встречаете ), уменьшайте счетчик уровня вложенности. Если уровень вложенности больше 0 перед уменьшением, добавьте ) в результат.
Верните результат, содержащий строку без крайних скобок из каждой примитивной строки.
public class Solution {
public string RemoveOuterParentheses(string s) {
var result = new StringBuilder();
int level = 0;
foreach (char c in s) {
if (c == '(') {
if (level > 0) {
result.Append(c);
}
level++;
} else {
level--;
if (level > 0) {
result.Append(c);
}
}
}
return result.ToString();
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1470. Shuffle the Array
Сложность: easy
Дан массив nums, состоящий из 2n элементов в форме [x1, x2, ..., xn, y1, y2, ..., yn].
Верните массив в форме [x1, y1, x2, y2, ..., xn, yn].
Пример:
👨💻 Алгоритм:
1⃣ Создайте массив result размером 2 * n.
2⃣ Итеративно пройдите по массиву nums от 0 до n - 1:
Сохраните элемент xi+1, то есть nums[i], в индекс 2 * i массива result.
Сохраните элемент yi+1, то есть nums[i + n], в индекс 2 * i + 1 массива result.
3⃣ Верните массив result.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан массив nums, состоящий из 2n элементов в форме [x1, x2, ..., xn, y1, y2, ..., yn].
Верните массив в форме [x1, y1, x2, y2, ..., xn, yn].
Пример:
Input: nums = [2,5,1,3,4,7], n = 3
Output: [2,3,5,4,1,7]
Explanation: Since x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 then the answer is [2,3,5,4,1,7].
Сохраните элемент xi+1, то есть nums[i], в индекс 2 * i массива result.
Сохраните элемент yi+1, то есть nums[i + n], в индекс 2 * i + 1 массива result.
public class Solution {
public int[] Shuffle(int[] nums, int n) {
int[] result = new int[2 * n];
for (int i = 0; i < n; ++i) {
result[2 * i] = nums[i];
result[2 * i + 1] = nums[n + i];
}
return result;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 870. Advantage Shuffle
Сложность: medium
Даны два целочисленных массива nums1 и nums2 одинаковой длины. Преимущество nums1 относительно nums2 — это количество индексов i, для которых nums1[i] > nums2[i].
Верните любую перестановку nums1, которая максимизирует его преимущество относительно nums2.
Пример:
👨💻 Алгоритм:
1⃣ Отсортируйте nums1 и nums2. Для каждой карты a из отсортированного nums1 определите, может ли она побить текущую наименьшую карту b из отсортированного nums2. Если да, добавьте a в assigned[b], если нет, добавьте a в remaining.
2⃣ После распределения всех карт из nums1, используйте assigned и remaining для построения итогового результата. Для каждой карты b из nums2, если assigned[b] не пуст, добавьте в результат последнюю карту из assigned[b], иначе добавьте последнюю карту из remaining.
3⃣ Верните итоговый результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Даны два целочисленных массива nums1 и nums2 одинаковой длины. Преимущество nums1 относительно nums2 — это количество индексов i, для которых nums1[i] > nums2[i].
Верните любую перестановку nums1, которая максимизирует его преимущество относительно nums2.
Пример:
Input: nums1 = [2,7,11,15], nums2 = [1,10,4,11]
Output: [2,11,7,15]
public class Solution {
public int[] AdvantageCount(int[] A, int[] B) {
var sortedA = A.OrderBy(x => x).ToArray();
var sortedB = B.Select((x, i) => new { Value = x, Index = i }).OrderBy(x => x.Value).ToArray();
var assigned = new Dictionary<int, Queue<int>>();
var remaining = new Queue<int>();
int j = 0;
foreach (var a in sortedA) {
if (a > sortedB[j].Value) {
if (!assigned.ContainsKey(sortedB[j].Value))
assigned[sortedB[j].Value] = new Queue<int>();
assigned[sortedB[j].Value].Enqueue(a);
j++;
} else {
remaining.Enqueue(a);
}
}
var result = new int[B.Length];
for (int i = 0; i < B.Length; i++) {
if (assigned.ContainsKey(B[i]) && assigned[B[i]].Count > 0) {
result[i] = assigned[B[i]].Dequeue();
} else {
result[i] = remaining.Dequeue();
}
}
return result;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1136. Parallel Courses
Сложность: medium
Вам дано целое число n, которое указывает, что есть n курсов, обозначенных от 1 до n. Вам также дан массив relations, где relations[i] = [prevCoursei, nextCoursei], представляющий собой зависимость между курсами: курс prevCoursei должен быть пройден до курса nextCoursei.
За один семестр вы можете взять любое количество курсов, при условии, что вы прошли все необходимые предварительные курсы в предыдущем семестре для тех курсов, которые вы собираетесь взять.
Верните минимальное количество семестров, необходимых для прохождения всех курсов. Если нет способа пройти все курсы, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Постройте направленный граф из зависимостей (relations).
2⃣ Реализуйте функцию dfsCheckCycle для проверки наличия цикла в графе.
3⃣ Реализуйте функцию dfsMaxPath для вычисления длины самого длинного пути в графе. Если цикл найден, верните -1. Иначе верните длину самого длинного пути.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дано целое число n, которое указывает, что есть n курсов, обозначенных от 1 до n. Вам также дан массив relations, где relations[i] = [prevCoursei, nextCoursei], представляющий собой зависимость между курсами: курс prevCoursei должен быть пройден до курса nextCoursei.
За один семестр вы можете взять любое количество курсов, при условии, что вы прошли все необходимые предварительные курсы в предыдущем семестре для тех курсов, которые вы собираетесь взять.
Верните минимальное количество семестров, необходимых для прохождения всех курсов. Если нет способа пройти все курсы, верните -1.
Пример:
Input: n = 3, relations = [[1,3],[2,3]]
Output: 2
Explanation: The figure above represents the given graph.
In the first semester, you can take courses 1 and 2.
In the second semester, you can take course 3.
public class Solution {
public int MinimumSemesters(int N, int[][] relations) {
var graph = new List<List<int>>(N + 1);
for (int i = 0; i < N + 1; ++i) {
graph.Add(new List<int>());
}
foreach (var relation in relations) {
graph[relation[0]].Add(relation[1]);
}
var visited = new int[N + 1];
for (int node = 1; node < N + 1; node++) {
if (DfsCheckCycle(node, graph, visited) == -1) {
return -1;
}
}
var visitedLength = new int[N + 1];
int maxLength = 1;
for (int node = 1; node < N + 1; node++) {
int length = DfsMaxPath(node, graph, visitedLength);
maxLength = Math.Max(length, maxLength);
}
return maxLength;
}
private int DfsCheckCycle(int node, List<List<int>> graph, int[] visited) {
if (visited[node] != 0) {
return visited[node];
} else {
visited[node] = -1;
}
foreach (var endNode in graph[node]) {
if (DfsCheckCycle(endNode, graph, visited) == -1) {
return -1;
}
}
visited[node] = 1;
return 1;
}
private int DfsMaxPath(int node, List<List<int>> graph, int[] visitedLength) {
if (visitedLength[node] != 0) {
return visitedLength[node];
}
int maxLength = 1;
foreach (var endNode in graph[node]) {
int length = DfsMaxPath(endNode, graph, visitedLength);
maxLength = Math.Max(length + 1, maxLength);
}
visitedLength[node] = maxLength;
return maxLength;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 299. Bulls and Cows
Сложность: medium
Вы играете в игру "Быки и коровы" со своим другом.
Вы записываете секретное число и просите своего друга угадать, что это за число. Когда ваш друг делает предположение, вы даете ему подсказку со следующей информацией:
Количество "быков", то есть цифры в предположении, которые находятся на правильной позиции.
Количество "коров", то есть цифры в предположении, которые есть в вашем секретном числе, но находятся на неправильной позиции. Конкретно, это не-бычьи цифры в предположении, которые можно переставить так, чтобы они стали быками.
Дано секретное число secret и предположение вашего друга guess, верните подсказку для предположения вашего друга.
Подсказка должна быть в формате "xAyB", где x — количество быков, а y — количество коров. Обратите внимание, что и secret, и guess могут содержать повторяющиеся цифры.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация счетчиков:
Инициализируйте количество быков и коров значениями ноль.
Создайте хеш-таблицу для хранения символов строки secret и их частот.
2⃣ Обход строки guess:
Для каждого символа ch в строке guess:
Если ch присутствует в строке secret:
Если текущий символ ch совпадает с символом на той же позиции в secret (ch == secret[idx]):
Увеличьте количество быков: bulls += 1.
Обновите количество коров, если количество текущего символа в хеш-таблице отрицательное или равно нулю (то есть этот символ уже использовался для коров): cows -= int(h[ch] <= 0).
Если текущий символ ch не совпадает с символом на той же позиции в secret (ch != secret[idx]):
Увеличьте количество коров, если количество текущего символа в хеш-таблице больше нуля: cows += int(h[ch] > 0).
Обновите хеш-таблицу, помечая текущий символ как использованный: h[ch] -= 1.
3⃣ Возврат результата:
Верните количество быков и коров в формате "xAyB".
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вы играете в игру "Быки и коровы" со своим другом.
Вы записываете секретное число и просите своего друга угадать, что это за число. Когда ваш друг делает предположение, вы даете ему подсказку со следующей информацией:
Количество "быков", то есть цифры в предположении, которые находятся на правильной позиции.
Количество "коров", то есть цифры в предположении, которые есть в вашем секретном числе, но находятся на неправильной позиции. Конкретно, это не-бычьи цифры в предположении, которые можно переставить так, чтобы они стали быками.
Дано секретное число secret и предположение вашего друга guess, верните подсказку для предположения вашего друга.
Подсказка должна быть в формате "xAyB", где x — количество быков, а y — количество коров. Обратите внимание, что и secret, и guess могут содержать повторяющиеся цифры.
Пример:
Input: secret = "1807", guess = "7810"
Output: "1A3B"
Explanation: Bulls are connected with a '|' and cows are underlined:
"1807"
|
"7810"
Инициализируйте количество быков и коров значениями ноль.
Создайте хеш-таблицу для хранения символов строки secret и их частот.
Для каждого символа ch в строке guess:
Если ch присутствует в строке secret:
Если текущий символ ch совпадает с символом на той же позиции в secret (ch == secret[idx]):
Увеличьте количество быков: bulls += 1.
Обновите количество коров, если количество текущего символа в хеш-таблице отрицательное или равно нулю (то есть этот символ уже использовался для коров): cows -= int(h[ch] <= 0).
Если текущий символ ch не совпадает с символом на той же позиции в secret (ch != secret[idx]):
Увеличьте количество коров, если количество текущего символа в хеш-таблице больше нуля: cows += int(h[ch] > 0).
Обновите хеш-таблицу, помечая текущий символ как использованный: h[ch] -= 1.
Верните количество быков и коров в формате "xAyB".
using System;
using System.Collections.Generic;
public class Solution {
public string GetHint(string secret, string guess) {
var h = new Dictionary<char, int>();
foreach (var ch in secret) {
if (!h.ContainsKey(ch)) {
h[ch] = 0;
}
h[ch]++;
}
int bulls = 0;
int cows = 0;
int n = guess.Length;
var secretArray = secret.ToCharArray();
var guessArray = guess.ToCharArray();
for (int idx = 0; idx < n; idx++) {
var ch = guessArray[idx];
if (h.ContainsKey(ch)) {
if (ch == secretArray[idx]) {
bulls++;
if (h[ch] <= 0) {
cows--;
}
} else {
if (h[ch] > 0) {
cows++;
}
}
h[ch]--;
}
}
return $"{bulls}A{cows}B";
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1120. Maximum Average Subtree
Сложность: medium
Дан корень бинарного дерева. Верните максимальное среднее значение поддерева этого дерева. Ответы, отличающиеся от фактического ответа не более чем на 10^-5, будут приняты.
Поддерево дерева — это любой узел этого дерева плюс все его потомки.
Среднее значение дерева — это сумма его значений, деленная на количество узлов.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и определение State:
Определите класс State для хранения количества узлов в поддереве, суммы значений узлов в поддереве и максимального среднего значения поддерева.
2⃣ Постобход (postorder traversal):
Реализуйте функцию maxAverage, которая выполняет постобход дерева, вычисляя nodeCount, valueSum и maxAverage для каждого узла, начиная с дочерних узлов и продвигаясь к родительским узлам.
3⃣ Вычисление максимального среднего значения:
Используйте значения, полученные от дочерних узлов, для вычисления среднего значения для текущего узла и обновите maxAverage, если новое среднее значение больше текущего максимума.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан корень бинарного дерева. Верните максимальное среднее значение поддерева этого дерева. Ответы, отличающиеся от фактического ответа не более чем на 10^-5, будут приняты.
Поддерево дерева — это любой узел этого дерева плюс все его потомки.
Среднее значение дерева — это сумма его значений, деленная на количество узлов.
Пример:
Input: root = [5,6,1]
Output: 6.00000
Explanation:
For the node with value = 5 we have an average of (5 + 6 + 1) / 3 = 4.
For the node with value = 6 we have an average of 6 / 1 = 6.
For the node with value = 1 we have an average of 1 / 1 = 1.
So the answer is 6 which is the maximum.
Определите класс State для хранения количества узлов в поддереве, суммы значений узлов в поддереве и максимального среднего значения поддерева.
Реализуйте функцию maxAverage, которая выполняет постобход дерева, вычисляя nodeCount, valueSum и maxAverage для каждого узла, начиная с дочерних узлов и продвигаясь к родительским узлам.
Используйте значения, полученные от дочерних узлов, для вычисления среднего значения для текущего узла и обновите maxAverage, если новое среднее значение больше текущего максимума.
public class Solution {
class State {
public int nodeCount;
public int valueSum;
public double maxAverage;
public State(int nodes, int sum, double maxAvg) {
this.nodeCount = nodes;
this.valueSum = sum;
this.maxAverage = maxAvg;
}
}
public double MaximumAverageSubtree(TreeNode root) {
return maxAverage(root).maxAverage;
}
private State maxAverage(TreeNode root) {
if (root == null) {
return new State(0, 0, 0);
}
State left = maxAverage(root.left);
State right = maxAverage(root.right);
int nodeCount = left.nodeCount + right.nodeCount + 1;
int sum = left.valueSum + right.valueSum + root.val;
double currentAverage = (1.0 * sum) / nodeCount;
double maxAverage = Math.Max(currentAverage, Math.Max(left.maxAverage, right.maxAverage));
return new State(nodeCount, sum, maxAverage);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 850. Rectangle Area II
Сложность: hard
Вам дан двумерный массив прямоугольников, выровненных по осям. Каждый прямоугольник[i] = [xi1, yi1, xi2, yi2] обозначает i-й прямоугольник, где (xi1, yi1) — координаты нижнего левого угла, а (xi2, yi2) — координаты верхнего правого угла.
Вычислите общую площадь, покрытую всеми прямоугольниками на плоскости. Любая площадь, покрытая двумя или более прямоугольниками, должна учитываться только один раз.
Верните общую площадь. Поскольку ответ может быть слишком большим, верните его по модулю 10^9 + 7.
Пример:
👨💻 Алгоритм:
1⃣ Переназначьте каждую x координату на 0, 1, 2, .... Аналогично, переназначьте все y координаты.
2⃣ Теперь мы имеем задачу, которую можно решить методом грубой силы: для каждого прямоугольника с переназначенными координатами (rx1, ry1, rx2, ry2) заполним сетку grid[x][y] = True для rx1 <= x < rx2 и ry1 <= y < ry2.
3⃣ Затем каждая ячейка grid[rx][ry] будет представлять площадь (imapx(rx+1) - imapx(rx)) * (imapy(ry+1) - imapy(ry)), где если x был переназначен на rx, то imapx(rx) = x ("обратная карта x для переназначенного x равна x"), аналогично для imapy.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Вам дан двумерный массив прямоугольников, выровненных по осям. Каждый прямоугольник[i] = [xi1, yi1, xi2, yi2] обозначает i-й прямоугольник, где (xi1, yi1) — координаты нижнего левого угла, а (xi2, yi2) — координаты верхнего правого угла.
Вычислите общую площадь, покрытую всеми прямоугольниками на плоскости. Любая площадь, покрытая двумя или более прямоугольниками, должна учитываться только один раз.
Верните общую площадь. Поскольку ответ может быть слишком большим, верните его по модулю 10^9 + 7.
Пример:
Input: rectangles = [[0,0,2,2],[1,0,2,3],[1,0,3,1]]
Output: 6
Explanation: A total area of 6 is covered by all three rectangles, as illustrated in the picture.
From (1,1) to (2,2), the green and red rectangles overlap.
From (1,0) to (2,3), all three rectangles overlap.
public class Solution {
public int RectangleArea(int[][] rectangles) {
int N = rectangles.Length;
HashSet<int> Xvals = new HashSet<int>();
HashSet<int> Yvals = new HashSet<int>();
foreach (var rec in rectangles) {
Xvals.Add(rec[0]);
Xvals.Add(rec[2]);
Yvals.Add(rec[1]);
Yvals.Add(rec[3]);
}
int[] imapx = Xvals.ToArray();
Array.Sort(imapx);
int[] imapy = Yvals.ToArray();
Array.Sort(imapy);
Dictionary<int, int> mapx = new Dictionary<int, int>();
Dictionary<int, int> mapy = new Dictionary<int, int>();
for (int i = 0; i < imapx.Length; ++i)
mapx[imapx[i]] = i;
for (int i = 0; i < imapy.Length; ++i)
mapy[imapy[i]] = i;
bool[,] grid = new bool[imapx.Length, imapy.Length];
foreach (var rec in rectangles)
for (int x = mapx[rec[0]]; x < mapx[rec[2]]; ++x)
for (int y = mapy[rec[1]]; y < mapy[rec[3]]; ++y)
grid[x, y] = true;
long ans = 0;
for (int x = 0; x < grid.GetLength(0); ++x)
for (int y = 0; y < grid.GetLength(1); ++y)
if (grid[x, y])
ans += (long)(imapx[x + 1] - imapx[x]) * (imapy[y + 1] - imapy[y]);
ans %= 1_000_000_007;
return (int)ans;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 78. Subsets
Сложность: medium
Дан массив целых чисел nums, содержащий уникальные элементы. Верните все возможные подмножества (степенной набор).
Множество решений не должно содержать дублирующихся подмножеств. Результат может быть возвращен в любом порядке.
Пример:
👨💻 Алгоритм:
1⃣ Определяем функцию обратного отслеживания под названием backtrack(first, curr), которая принимает индекс первого элемента, который нужно добавить, и текущую комбинацию в качестве аргументов.
2⃣ Если текущая комбинация завершена, мы добавляем её в итоговый вывод.
3⃣ В противном случае перебираем индексы i от first до длины всей последовательности n, добавляем элемент nums[i] в текущую комбинацию curr, продолжаем добавлять больше чисел в комбинацию: backtrack(i + 1, curr) и возвращаемся, удаляя nums[i] из curr.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив целых чисел nums, содержащий уникальные элементы. Верните все возможные подмножества (степенной набор).
Множество решений не должно содержать дублирующихся подмножеств. Результат может быть возвращен в любом порядке.
Пример:
Input: nums = [1,2,3]
Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
class Solution {
private List<IList<int>> output = new List<IList<int>>();
private int n, k;
private void backtrack(int first, List<int> curr, int[] nums) {
if (curr.Count == k) output.Add(new List<int>(curr));
for (int i = first; i < n; ++i) {
curr.Add(nums[i]);
backtrack(i + 1, curr, nums);
curr.RemoveAt(curr.Count - 1);
}
}
public IList<IList<int>> Subsets(int[] nums) {
n = nums.Length;
for (k = 0; k < n + 1; ++k) {
backtrack(0, new List<int>(), nums);
}
return output;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 496. Next Greater Element I
Сложность: easy
Следующий больший элемент для некоторого элемента x в массиве — это первый больший элемент, который находится справа от x в том же массиве.
Вам даны два различных целочисленных массива с индексами, начинающимися с 0: nums1 и nums2, где nums1 является подмножеством nums2.
Для каждого 0 <= i < nums1.length найдите индекс j, такой что nums1[i] == nums2[j], и определите следующий больший элемент для nums2[j] в nums2. Если следующего большего элемента нет, то ответ для этого запроса — -1.
Верните массив ans длиной nums1.length, где ans[i] — это следующий больший элемент, как описано выше.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и поиск совпадений
Создайте массив res для хранения результатов. Для каждого элемента nums1[i] найдите его индекс j в массиве nums2.
2⃣ Поиск следующего большего элемента
После нахождения индекса j в nums2 начните поиск элемента справа от nums2[j], который больше nums1[i]. Если такой элемент найден, добавьте его в res.
3⃣ Заполнение результата
Если следующий больший элемент не найден, добавьте -1 в соответствующую позицию res. Верните массив res.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Следующий больший элемент для некоторого элемента x в массиве — это первый больший элемент, который находится справа от x в том же массиве.
Вам даны два различных целочисленных массива с индексами, начинающимися с 0: nums1 и nums2, где nums1 является подмножеством nums2.
Для каждого 0 <= i < nums1.length найдите индекс j, такой что nums1[i] == nums2[j], и определите следующий больший элемент для nums2[j] в nums2. Если следующего большего элемента нет, то ответ для этого запроса — -1.
Верните массив ans длиной nums1.length, где ans[i] — это следующий больший элемент, как описано выше.
Пример:
Input: nums1 = [4,1,2], nums2 = [1,3,4,2]
Output: [-1,3,-1]
Explanation: The next greater element for each value of nums1 is as follows:
- 4 is underlined in nums2 = [1,3,4,2]. There is no next greater element, so the answer is -1.
- 1 is underlined in nums2 = [1,3,4,2]. The next greater element is 3.
- 2 is underlined in nums2 = [1,3,4,2]. There is no next greater element, so the answer is -1.
Создайте массив res для хранения результатов. Для каждого элемента nums1[i] найдите его индекс j в массиве nums2.
После нахождения индекса j в nums2 начните поиск элемента справа от nums2[j], который больше nums1[i]. Если такой элемент найден, добавьте его в res.
Если следующий больший элемент не найден, добавьте -1 в соответствующую позицию res. Верните массив res.
public class Solution {
public int[] NextGreaterElement(int[] nums1, int[] nums2) {
int[] res = new int[nums1.Length];
Array.Fill(res, -1);
for (int i = 0; i < nums1.Length; i++) {
bool found = false;
for (int j = 0; j < nums2.Length; j++) {
if (nums2[j] == nums1[i]) {
found = true;
}
if (found && nums2[j] > nums1[i]) {
res[i] = nums2[j];
break;
}
}
}
return res;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1242. Web Crawler Multithreaded
Сложность: medium
Учитывая URL startUrl и интерфейс HtmlParser, реализуйте многопоточный веб-краулер, который будет просматривать все ссылки, находящиеся под тем же именем хоста, что и startUrl. Верните все URL, полученные вашим веб-краулером, в любом порядке.
Ваш краулер должен: Начинать со страницы: startUrl Вызывать HtmlParser.getUrls(url), чтобы получить все URL с веб-страницы данного URL. Не просматривать одну и ту же ссылку дважды. Исследовать только те ссылки, которые находятся под тем же именем хоста, что и startUrl.
Пример:
👨💻 Алгоритм:
1⃣ Извлечь имя хоста из startUrl.
Использовать многопоточность для обработки URL-адресов.
2⃣ Хранить посещенные URL-адреса, чтобы избежать повторного посещения.
3⃣ Использовать HtmlParser для получения URL-адресов с веб-страниц.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: 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"
]
Использовать многопоточность для обработки URL-адресов.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
public class HtmlParser {
public List<string> GetUrls(string url) {
return new List<string>();
}
}
public class Solution {
private ConcurrentDictionary<string, bool> visited = new ConcurrentDictionary<string, bool>();
private string hostname;
private HtmlParser htmlParser;
public IList<string> Crawl(string startUrl, HtmlParser htmlParser) {
this.hostname = new Uri(startUrl).Host;
this.htmlParser = htmlParser;
var tasks = new List<Task>();
visited.TryAdd(startUrl, true);
tasks.Add(Task.Run(() => Visit(startUrl)));
Task.WaitAll(tasks.ToArray());
return visited.Keys.ToList();
}
private async Task Visit(string url) {
foreach (var nextUrl in htmlParser.GetUrls(url)) {
if (new Uri(nextUrl).Host == hostname && visited.TryAdd(nextUrl, true)) {
await Visit(nextUrl);
}
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1464. Maximum Product of Two Elements in an Array
Сложность: easy
Дан массив целых чисел nums, выберите два разных индекса i и j этого массива. Верните максимальное значение (nums[i]-1)*(nums[j]-1).
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте biggest = 0 и secondBiggest = 0.
2⃣ Итерируйте по каждому элементу массива nums:
Если текущий элемент больше biggest, обновите secondBiggest = biggest и biggest = текущий элемент.
Иначе обновите secondBiggest, если текущий элемент больше secondBiggest.
3⃣ Верните (biggest - 1) * (secondBiggest - 1).
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан массив целых чисел nums, выберите два разных индекса i и j этого массива. Верните максимальное значение (nums[i]-1)*(nums[j]-1).
Пример:
Input: nums = [3,4,5,2]
Output: 12
Explanation: If you choose the indices i=1 and j=2 (indexed from 0), you will get the maximum value,
that is, (nums[1]-1)*(nums[2]-1) = (4-1)*(5-1) = 3*4 = 12.
Если текущий элемент больше biggest, обновите secondBiggest = biggest и biggest = текущий элемент.
Иначе обновите secondBiggest, если текущий элемент больше secondBiggest.
public class Solution {
public int MaxProduct(int[] nums) {
int biggest = 0;
int secondBiggest = 0;
foreach (int num in nums) {
if (num > biggest) {
secondBiggest = biggest;
biggest = num;
} else if (num > secondBiggest) {
secondBiggest = num;
}
}
return (biggest - 1) * (secondBiggest - 1);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 826. Most Profit Assigning Work
Сложность: medium
У вас есть n заданий и m рабочих. Вам даны три массива: difficulty, profit и worker, где:
difficulty[i] и profit[i] — сложность и прибыль i-го задания,
worker[j] — способность j-го рабочего (т.е. j-й рабочий может выполнить задание со сложностью не больше worker[j]).
Каждому рабочему можно назначить не более одного задания, но одно задание может быть выполнено несколько раз.
Например, если три рабочих выполняют одно и то же задание с оплатой $1, общая прибыль составит $3. Если рабочий не может выполнить ни одно задание, его прибыль равна $0.
Верните максимальную прибыль, которую можно получить после распределения рабочих по заданиям.
Пример:
👨💻 Алгоритм:
1⃣ Создание и сортировка профиля работы
Инициализируйте массив пар jobProfile с {0, 0}. Для каждого задания добавьте {difficulty[i], profit[i]} в jobProfile. Отсортируйте jobProfile по возрастанию сложности.
2⃣ Обновление максимальной прибыли для каждой сложности
Обновите значение прибыли каждой сложности, чтобы оно было максимальным из текущего значения и предыдущего значения прибыли.
3⃣ Вычисление максимальной прибыли
Для каждой способности рабочего используйте бинарный поиск, чтобы найти задание с наибольшей прибылью, которую может выполнить этот рабочий. Суммируйте полученную прибыль для всех рабочих и верните ее.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
У вас есть n заданий и m рабочих. Вам даны три массива: difficulty, profit и worker, где:
difficulty[i] и profit[i] — сложность и прибыль i-го задания,
worker[j] — способность j-го рабочего (т.е. j-й рабочий может выполнить задание со сложностью не больше worker[j]).
Каждому рабочему можно назначить не более одного задания, но одно задание может быть выполнено несколько раз.
Например, если три рабочих выполняют одно и то же задание с оплатой $1, общая прибыль составит $3. Если рабочий не может выполнить ни одно задание, его прибыль равна $0.
Верните максимальную прибыль, которую можно получить после распределения рабочих по заданиям.
Пример:
Input: difficulty = [2,4,6,8,10], profit = [10,20,30,40,50], worker = [4,5,6,7]
Output: 100
Explanation: Workers are assigned jobs of difficulty [4,4,6,6] and they get a profit of [20,20,30,30] separately.
Инициализируйте массив пар jobProfile с {0, 0}. Для каждого задания добавьте {difficulty[i], profit[i]} в jobProfile. Отсортируйте jobProfile по возрастанию сложности.
Обновите значение прибыли каждой сложности, чтобы оно было максимальным из текущего значения и предыдущего значения прибыли.
Для каждой способности рабочего используйте бинарный поиск, чтобы найти задание с наибольшей прибылью, которую может выполнить этот рабочий. Суммируйте полученную прибыль для всех рабочих и верните ее.
public class Solution {
public int MaxProfitAssignment(int[] difficulty, int[] profit, int[] worker) {
var jobProfile = new List<int[]> { new int[] { 0, 0 } };
for (int i = 0; i < difficulty.Length; i++) {
jobProfile.Add(new int[] { difficulty[i], profit[i] });
}
jobProfile.Sort((a, b) => a[0].CompareTo(b[0]));
for (int i = 1; i < jobProfile.Count; i++) {
jobProfile[i][1] = Math.Max(jobProfile[i][1], jobProfile[i - 1][1]);
}
int netProfit = 0;
foreach (int ability in worker) {
int l = 0, r = jobProfile.Count - 1, jobProfit = 0;
while (l <= r) {
int mid = (l + r) / 2;
if (jobProfile[mid][0] <= ability) {
jobProfit = Math.Max(jobProfit, jobProfile[mid][1]);
l = mid + 1;
} else {
r = mid - 1;
}
}
netProfit += jobProfit;
}
return netProfit;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: CodeTestcaseTest ResultTest Result1523. Count Odd Numbers in an Interval Range
Сложность: easy
### Условие задачи
Даны два неотрицательных целых числа low и high. Верните количество нечётных чисел между low и high (включительно).
Пример:
👨💻 Алгоритм:
1⃣ Проверьте, является ли число low нечётным. Это можно легко сделать с помощью оператора %, но мы используем побитовый оператор &, так как он более эффективен.
2⃣ Если low нечётное, увеличьте его на 1.
3⃣ Верните (high - low) / 2 + 1. Важный момент здесь - проверить, не стало ли low больше, чем high после увеличения. Это произойдёт, если low = high, и в этом случае следует вернуть 0.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
### Условие задачи
Даны два неотрицательных целых числа low и high. Верните количество нечётных чисел между low и high (включительно).
Пример:
Input: low = 3, high = 7
Output: 3
Explanation: The odd numbers between 3 and 7 are [3,5,7].
public class Solution {
public int CountOdds(int low, int high) {
if ((low & 1) == 0) {
low++;
}
return low > high ? 0 : (high - low) / 2 + 1;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 363. Max Sum of Rectangle No Larger Than K
Сложность: hard
Дана матрица размером m x n и целое число k, вернуть максимальную сумму прямоугольника в матрице, такая что его сумма не превышает k.
Гарантируется, что будет прямоугольник с суммой, не превышающей k.
Пример:
👨💻 Алгоритм:
1⃣ Создать вспомогательную функцию updateResult, которая будет находить максимальную сумму подмассива в одномерном массиве, не превышающую k.
2⃣ Преобразовать каждую подматрицу в одномерный массив и применить к ней функцию updateResult.
3⃣ Вернуть максимальную найденную сумму.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Дана матрица размером m x n и целое число k, вернуть максимальную сумму прямоугольника в матрице, такая что его сумма не превышает k.
Гарантируется, что будет прямоугольник с суммой, не превышающей k.
Пример:
Input: matrix = [[1,0,1],[0,-2,3]], k = 2
Output: 2
Explanation: Because the sum of the blue rectangle [[0, 1], [-2, 3]] is 2, and 2 is the max number no larger than k (k = 2).
using System;
using System.Collections.Generic;
public class Solution {
private int result = int.MinValue;
private void UpdateResult(int[] nums, int k) {
int sum = 0;
var sortedSum = new SortedSet<int> { 0 };
foreach (int num in nums) {
sum += num;
var x = sortedSum.GetViewBetween(sum - k, int.MaxValue);
if (x.Count > 0) {
result = Math.Max(result, sum - x.Min);
}
sortedSum.Add(sum);
}
}
public int MaxSumSubmatrix(int[][] matrix, int k) {
int rows = matrix.Length;
int cols = matrix[0].Length;
for (int i = 0; i < rows; i++) {
var rowSum = new int[cols];
for (int row = i; row < rows; row++) {
for (int col = 0; col < cols; col++) {
rowSum[col] += matrix[row][col];
}
UpdateResult(rowSum, k);
if (result == k) {
return result;
}
}
}
return result;
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 659. Split Array into Consecutive Subsequences
Сложность: medium
Вам дан отсортированный в неубывающем порядке массив целых чисел nums.
Определите, можно ли разделить nums на одну или несколько подпоследовательностей так, чтобы выполнялись оба следующих условия:
Каждая подпоследовательность является последовательностью последовательных возрастающих чисел (то есть каждое целое число на 1 больше предыдущего).
Все подпоследовательности имеют длину 3 или более.
Верните true, если можно разделить nums согласно вышеуказанным условиям, или false в противном случае.
Подпоследовательность массива — это новый массив, который формируется из исходного массива путем удаления некоторых (может быть, ни одного) элементов без нарушения относительных позиций оставшихся элементов. (например, [1,3,5] является подпоследовательностью [1,2,3,4,5], тогда как [1,3,2] не является).
Пример:
👨💻 Алгоритм:
1⃣ Подсчет частоты элементов:
Создайте хеш-таблицу для подсчета количества вхождений каждого элемента в массиве nums.
2⃣ Создание подпоследовательностей:
Создайте хеш-таблицу для отслеживания количества подпоследовательностей, которые могут быть продолжены для каждого элемента.
Пройдите по каждому элементу в массиве и выполните следующие действия:
Если элемент можно добавить к существующей подпоследовательности (проверяя хеш-таблицу подпоследовательностей), добавьте его и обновите хеш-таблицу.
Если элемент нельзя добавить к существующей подпоследовательности, начните новую последовательность длиной 3 или более элементов.
Если ни одно из условий не выполнено, верните false.
3⃣ Проверка результата:
Верните true, если все элементы успешно распределены по подпоследовательностям.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан отсортированный в неубывающем порядке массив целых чисел nums.
Определите, можно ли разделить nums на одну или несколько подпоследовательностей так, чтобы выполнялись оба следующих условия:
Каждая подпоследовательность является последовательностью последовательных возрастающих чисел (то есть каждое целое число на 1 больше предыдущего).
Все подпоследовательности имеют длину 3 или более.
Верните true, если можно разделить nums согласно вышеуказанным условиям, или false в противном случае.
Подпоследовательность массива — это новый массив, который формируется из исходного массива путем удаления некоторых (может быть, ни одного) элементов без нарушения относительных позиций оставшихся элементов. (например, [1,3,5] является подпоследовательностью [1,2,3,4,5], тогда как [1,3,2] не является).
Пример:
Input: nums = [1,2,3,3,4,5]
Output: true
Создайте хеш-таблицу для подсчета количества вхождений каждого элемента в массиве nums.
Создайте хеш-таблицу для отслеживания количества подпоследовательностей, которые могут быть продолжены для каждого элемента.
Пройдите по каждому элементу в массиве и выполните следующие действия:
Если элемент можно добавить к существующей подпоследовательности (проверяя хеш-таблицу подпоследовательностей), добавьте его и обновите хеш-таблицу.
Если элемент нельзя добавить к существующей подпоследовательности, начните новую последовательность длиной 3 или более элементов.
Если ни одно из условий не выполнено, верните false.
Верните true, если все элементы успешно распределены по подпоследовательностям.
using System.Collections.Generic;
public class Solution {
public bool IsPossible(int[] nums) {
var freq = new Dictionary<int, int>();
var need = new Dictionary<int, int>();
foreach (var num in nums) {
if (freq.ContainsKey(num)) {
freq[num]++;
} else {
freq[num] = 1;
}
}
foreach (var num in nums) {
if (freq[num] == 0) continue;
if (need.ContainsKey(num) && need[num] > 0) {
need[num]--;
if (need.ContainsKey(num + 1)) {
need[num + 1]++;
} else {
need[num + 1] = 1;
}
} else if (freq.ContainsKey(num + 1) && freq[num + 1] > 0 &&
freq.ContainsKey(num + 2) && freq[num + 2] > 0) {
freq[num + 1]--;
freq[num + 2]--;
if (need.ContainsKey(num + 3)) {
need[num + 3]++;
} else {
need[num + 3] = 1;
}
} else {
return false;
}
freq[num]--;
}
return true;
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 149. Max Points on a Line
Сложность: hard
Дан массив точек, где points[i] = [xi, yi] представляет точку на плоскости XY. Верните максимальное количество точек, которые лежат на одной прямой.
Пример:
👨💻 Алгоритм:
1⃣ Итерация по всем точкам:
Проходим по всем точкам массива. Пусть текущая точка будет points[i]. Создаём хеш-таблицу cnt для подсчёта углов.
2⃣ Расчёт углов и подсчёт:
Для каждой точки j, не равной i, рассчитываем арктангенс вектора points[j] - points[i] и добавляем это значение в хеш-таблицу
3⃣ Обновление ответа:
Пусть k будет максимальным количеством вхождений какого-либо значения угла в хеш-таблице. Обновляем ответ значением k + 1 (прибавляем 1, потому что точка points[i] также лежит на этой линии, и её нужно включить в ответ).
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Дан массив точек, где points[i] = [xi, yi] представляет точку на плоскости XY. Верните максимальное количество точек, которые лежат на одной прямой.
Пример:
Input: points = [[1,1],[2,2],[3,3]]
Output: 3
Проходим по всем точкам массива. Пусть текущая точка будет points[i]. Создаём хеш-таблицу cnt для подсчёта углов.
Для каждой точки j, не равной i, рассчитываем арктангенс вектора points[j] - points[i] и добавляем это значение в хеш-таблицу
Пусть k будет максимальным количеством вхождений какого-либо значения угла в хеш-таблице. Обновляем ответ значением k + 1 (прибавляем 1, потому что точка points[i] также лежит на этой линии, и её нужно включить в ответ).
public class Solution {
public int MaxPoints(int[][] points) {
int n = points.Length;
if (n == 1) {
return 1;
}
int result = 2;
for (int i = 0; i < n; i++) {
Dictionary<double, int> cnt = new Dictionary<double, int>();
for (int j = 0; j < n; j++) {
if (j != i) {
double key = Math.Atan2(points[j][1] - points[i][1],
points[j][0] - points[i][0]);
if (cnt.ContainsKey(key)) {
cnt[key]++;
} else {
cnt[key] = 1;
}
}
}
result = Math.Max(result, cnt.Values.Max() + 1);
}
return result;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 813. Largest Sum of Averages
Сложность: medium
Вам дан целочисленный массив nums и целое число k. Вы можете разбить массив на не более чем k непустых смежных подмассивов. Оценка разбиения равна сумме средних значений каждого подмассива.
Обратите внимание, что при разбиении должны быть использованы все целые числа из nums, и что оценка не обязательно является целым числом.
Верните максимальную оценку, которую можно достичь среди всех возможных разбиений. Ответы, отличающиеся от фактического ответа не более чем на 10^-6, будут приняты.
Пример:
👨💻 Алгоритм:
1⃣ Пусть dp(i, k) будет лучшей оценкой для разбиения массива A[i:] на не более чем k частей. Если первая группа, в которую мы разбиваем A[i:], заканчивается перед j, тогда наше разбиение-кандидат имеет оценку average(i, j) + dp(j, k-1), где average(i, j) = (A[i] + A[i+1] + ... + A[j-1]) / (j - i) (деление с плавающей запятой). Мы берем наивысшую оценку из этих вариантов, помня, что разбиение необязательно - dp(i, k) также может быть просто average(i, N).
2⃣ В общем случае наша рекурсия выглядит так: dp(i, k) = max(average(i, N), max_{j > i}(average(i, j) + dp(j, k-1))). Мы можем рассчитывать average немного быстрее, используя префиксные суммы. Если P[x+1] = A[0] + A[1] + ... + A[x], тогда average(i, j) = (P[j] - P[i]) / (j - i).
3⃣ Наша реализация демонстрирует подход "снизу вверх" для динамического программирования. На шаге k во внешнем цикле, dp[i] представляет собой dp(i, k) из обсуждения выше, и мы рассчитываем следующий слой dp(i, k+1). Завершение второго цикла для i = 0..N-1 означает завершение расчета правильного значения для dp(i, t), а внутренний цикл выполняет расчет max_{j > i}(average(i, j) + dp(j, k)).
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан целочисленный массив nums и целое число k. Вы можете разбить массив на не более чем k непустых смежных подмассивов. Оценка разбиения равна сумме средних значений каждого подмассива.
Обратите внимание, что при разбиении должны быть использованы все целые числа из nums, и что оценка не обязательно является целым числом.
Верните максимальную оценку, которую можно достичь среди всех возможных разбиений. Ответы, отличающиеся от фактического ответа не более чем на 10^-6, будут приняты.
Пример:
Input: nums = [9,1,2,3,9], k = 3
Output: 20.00000
Explanation:
The best choice is to partition nums into [9], [1, 2, 3], [9]. The answer is 9 + (1 + 2 + 3) / 3 + 9 = 20.
We could have also partitioned nums into [9, 1], [2], [3, 9], for example.
That partition would lead to a score of 5 + 2 + 6 = 13, which is worse.
using System;
public class Solution {
public double LargestSumOfAverages(int[] A, int K) {
int N = A.Length;
double[] P = new double[N + 1];
// Префиксные суммы
for (int i = 0; i < N; ++i)
P[i + 1] = P[i] + A[i];
double[] dp = new double[N];
for (int i = 0; i < N; ++i)
dp[i] = (P[N] - P[i]) / (N - i);
for (int k = 0; k < K - 1; ++k) {
for (int i = 0; i < N; ++i) {
for (int j = i + 1; j < N; ++j) {
dp[i] = Math.Max(dp[i], (P[j] - P[i]) / (j - i) + dp[j]);
}
}
}
return dp[0];
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 531. Lonely Pixel I
Сложность: medium
Дано изображение размером m x n, состоящее из чёрных ('B') и белых ('W') пикселей. Верните количество чёрных одиночных пикселей.
Чёрный одиночный пиксель — это символ 'B', расположенный в такой позиции, где в той же строке и в том же столбце нет других чёрных пикселей.
Пример:
👨💻 Алгоритм:
1⃣ Подсчёт количества чёрных пикселей в строках и столбцах:
Пройдите по всей матрице picture, для каждой чёрной клетки (x, y) увеличивайте rowCount[x] и colCount[y] на 1.
2⃣ Поиск одиночных чёрных пикселей:
Снова пройдите по всей матрице и для каждой чёрной клетки (x, y) проверьте значения rowCount[x] и colCount[y]. Если оба значения равны 1, увеличьте переменную answer на 1.
3⃣ Возврат результата:
Верните answer.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дано изображение размером m x n, состоящее из чёрных ('B') и белых ('W') пикселей. Верните количество чёрных одиночных пикселей.
Чёрный одиночный пиксель — это символ 'B', расположенный в такой позиции, где в той же строке и в том же столбце нет других чёрных пикселей.
Пример:
Input: picture = [["W","W","B"],["W","B","W"],["B","W","W"]]
Output: 3
Explanation: All the three 'B's are black lonely pixels.
Пройдите по всей матрице picture, для каждой чёрной клетки (x, y) увеличивайте rowCount[x] и colCount[y] на 1.
Снова пройдите по всей матрице и для каждой чёрной клетки (x, y) проверьте значения rowCount[x] и colCount[y]. Если оба значения равны 1, увеличьте переменную answer на 1.
Верните answer.
public class Solution {
public int FindLonelyPixel(char[][] picture) {
int n = picture.Length;
int m = picture[0].Length;
int[] rowCount = new int[n];
int[] columnCount = new int[m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (picture[i][j] == 'B') {
rowCount[i]++;
columnCount[j]++;
}
}
}
int answer = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (picture[i][j] == 'B' && rowCount[i] == 1 && columnCount[j] == 1) {
answer++;
}
}
}
return answer;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 646. Maximum Length of Pair Chain
Сложность: medium
Вам дан массив из n пар, где pairs[i] = [lefti, righti] и lefti < righti. Пара p2 = [c, d] следует за парой p1 = [a, b], если b < c. Таким образом можно построить цепочку пар. Верните самую длинную цепочку, которую можно составить. Вам не нужно использовать все заданные интервалы. Вы можете выбирать пары в любом порядке.
Пример:
👨💻 Алгоритм:
1⃣ Отсортируйте пары по второму элементу каждой пары (righti).
2⃣ Используйте динамическое программирование или жадный алгоритм, чтобы построить цепочку максимальной длины.
3⃣ Переберите отсортированные пары и выберите пары, которые могут следовать одна за другой, увеличивая длину цепочки.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан массив из n пар, где pairs[i] = [lefti, righti] и lefti < righti. Пара p2 = [c, d] следует за парой p1 = [a, b], если b < c. Таким образом можно построить цепочку пар. Верните самую длинную цепочку, которую можно составить. Вам не нужно использовать все заданные интервалы. Вы можете выбирать пары в любом порядке.
Пример:
Input: nums = [1,2,2,4]
Output: [2,3]
public class Solution {
public int FindLongestChain(int[][] pairs) {
Array.Sort(pairs, (a, b) => a[1] - b[1]);
int currentEnd = int.MinValue;
int count = 0;
foreach (var pair in pairs) {
if (currentEnd < pair[0]) {
currentEnd = pair[1];
count++;
}
}
return count;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM