Задача: 1192. Critical Connections in a Network
Сложность: hard
Существует n серверов, пронумерованных от 0 до n - 1, соединенных неориентированными соединениями "сервер-сервер", образуя сеть, где connections[i] = [ai, bi] представляет собой соединение между серверами ai и bi. Любой сервер может достичь других серверов напрямую или косвенно через сеть.
Критическое соединение — это соединение, удаление которого сделает невозможным достижение некоторыми серверами других серверов.
Верните все критические соединения в сети в любом порядке.
Пример:
👨💻 Алгоритм:
1⃣ Построение графа и инициализация:
Постройте граф в виде списка смежности и создайте словарь для хранения соединений.
Инициализируйте ранги для узлов.
2⃣ Поиск в глубину (DFS):
Реализуйте функцию dfs для обхода графа.
Обновите ранги узлов и определите минимальный ранг для текущего узла.
Проверьте, можно ли удалить текущее соединение, и обновите минимальный ранг.
3⃣ Поиск критических соединений:
После завершения обхода DFS преобразуйте оставшиеся соединения в список и верните его.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Существует n серверов, пронумерованных от 0 до n - 1, соединенных неориентированными соединениями "сервер-сервер", образуя сеть, где connections[i] = [ai, bi] представляет собой соединение между серверами ai и bi. Любой сервер может достичь других серверов напрямую или косвенно через сеть.
Критическое соединение — это соединение, удаление которого сделает невозможным достижение некоторыми серверами других серверов.
Верните все критические соединения в сети в любом порядке.
Пример:
Input: n = 4, connections = [[0,1],[1,2],[2,0],[1,3]]
Output: [[1,3]]
Explanation: [[3,1]] is also accepted.
Постройте граф в виде списка смежности и создайте словарь для хранения соединений.
Инициализируйте ранги для узлов.
Реализуйте функцию dfs для обхода графа.
Обновите ранги узлов и определите минимальный ранг для текущего узла.
Проверьте, можно ли удалить текущее соединение, и обновите минимальный ранг.
После завершения обхода DFS преобразуйте оставшиеся соединения в список и верните его.
class Solution {
public:
vector<vector<int>> criticalConnections(int n, vector<vector<int>>& connections) {
formGraph(n, connections);
dfs(0, 0);
vector<vector<int>> result;
for (auto& conn : connDict) {
result.push_back({conn.first.first, conn.first.second});
}
return result;
}
private:
unordered_map<int, vector<int>> graph;
unordered_map<int, int> rank;
map<pair<int, int>, bool> connDict;
void formGraph(int n, vector<vector<int>>& connections) {
for (int i = 0; i < n; ++i) {
graph[i] = vector<int>();
rank[i] = -1;
}
for (auto& edge : connections) {
int u = edge[0], v = edge[1];
graph[u].push_back(v);
graph[v].push_back(u);
connDict[{min(u, v), max(u, v)}] = true;
}
}
int dfs(int node, int discoveryRank) {
if (rank[node] != -1) {
return rank[node];
}
rank[node] = discoveryRank;
int minRank = discoveryRank + 1;
for (int neighbor : graph[node]) {
if (rank[neighbor] != -1 && rank[neighbor] == discoveryRank - 1) {
continue;
}
int recursiveRank = dfs(neighbor, discoveryRank + 1);
if (recursiveRank <= discoveryRank) {
connDict.erase({min(node, neighbor), max(node, neighbor)});
}
minRank = min(minRank, recursiveRank);
}
return minRank;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1335. Minimum Difficulty of a Job Schedule
Сложность: hard
Вы хотите составить расписание списка заданий на d дней. Задания зависят друг от друга (т.е. чтобы выполнить задание i, вы должны закончить все задания j, где 0 <= j < i).
Вы должны выполнять как минимум одно задание каждый день. Сложность расписания заданий — это сумма сложностей каждого дня из d дней. Сложность дня — это максимальная сложность задания, выполненного в этот день.
Вам дан массив целых чисел jobDifficulty и целое число d. Сложность i-го задания равна jobDifficulty[i].
Верните минимальную сложность расписания заданий. Если вы не можете найти расписание для заданий, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Определение состояния:
Индекс i (индекс первой задачи на сегодняшний день в массиве jobDifficulty) и день d (количество оставшихся дней) будут определять состояние динамического программирования. min_diff(i, d) обозначает минимальную сложность при начале с i-й задачи с оставшимися d днями. min_diff(0, d) будет окончательным ответом, так как он представляет начало с начала массива задач и завершение всех задач за ровно d дней.
2⃣ Функция перехода состояния:
Задача с индексом j будет первой задачей на следующий день, следовательно, задачи, которые должны быть завершены сегодня, это все задачи с индексами между i и j, то есть jobDifficulty[i
]. Поскольку сложность дня — это максимальная сложность выполненной в этот день задачи, к сумме сложностей задач будет добавляться максимум из jobDifficulty[i
]. Формулируем функцию перехода состояния следующим образом: min_diff(i, d) = min_diff(j, d - 1) + max(jobDifficulty[i
]) для всех j > i.
3⃣ Базовый случай:
Когда остается только 1 день, необходимо завершить все незавершенные задачи в этот день и увеличить сложность расписания задач на максимальную сложность этих задач.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Вы хотите составить расписание списка заданий на d дней. Задания зависят друг от друга (т.е. чтобы выполнить задание i, вы должны закончить все задания j, где 0 <= j < i).
Вы должны выполнять как минимум одно задание каждый день. Сложность расписания заданий — это сумма сложностей каждого дня из d дней. Сложность дня — это максимальная сложность задания, выполненного в этот день.
Вам дан массив целых чисел jobDifficulty и целое число d. Сложность i-го задания равна jobDifficulty[i].
Верните минимальную сложность расписания заданий. Если вы не можете найти расписание для заданий, верните -1.
Пример:
Input: jobDifficulty = [6,5,4,3,2,1], d = 2
Output: 7
Explanation: First day you can finish the first 5 jobs, total difficulty = 6.
Second day you can finish the last job, total difficulty = 1.
The difficulty of the schedule = 6 + 1 = 7
Индекс i (индекс первой задачи на сегодняшний день в массиве jobDifficulty) и день d (количество оставшихся дней) будут определять состояние динамического программирования. min_diff(i, d) обозначает минимальную сложность при начале с i-й задачи с оставшимися d днями. min_diff(0, d) будет окончательным ответом, так как он представляет начало с начала массива задач и завершение всех задач за ровно d дней.
Задача с индексом j будет первой задачей на следующий день, следовательно, задачи, которые должны быть завершены сегодня, это все задачи с индексами между i и j, то есть jobDifficulty[i
]. Поскольку сложность дня — это максимальная сложность выполненной в этот день задачи, к сумме сложностей задач будет добавляться максимум из jobDifficulty[i
]. Формулируем функцию перехода состояния следующим образом: min_diff(i, d) = min_diff(j, d - 1) + max(jobDifficulty[i
]) для всех j > i.
Когда остается только 1 день, необходимо завершить все незавершенные задачи в этот день и увеличить сложность расписания задач на максимальную сложность этих задач.
class Solution {
public:
int minDifficulty(vector<int>& jobDifficulty, int d) {
int n = jobDifficulty.size();
if (n < d) {
return -1;
}
vector<vector<int>> mem(n, vector<int>(d + 1, -1));
return minDiff(0, d, jobDifficulty, mem);
}
private:
int minDiff(int i, int daysRemaining, vector<int>& jobDifficulty, vector<vector<int>>& mem) {
if (mem[i][daysRemaining] != -1) {
return mem[i][daysRemaining];
}
if (daysRemaining == 1) {
int res = 0;
for (int j = i; j < jobDifficulty.size(); j++) {
res = max(res, jobDifficulty[j]);
}
return res;
}
int res = INT_MAX;
int dailyMaxJobDiff = 0;
for (int j = i; j < jobDifficulty.size() - daysRemaining + 1; j++) {
dailyMaxJobDiff = max(dailyMaxJobDiff, jobDifficulty[j]);
res = min(res, dailyMaxJobDiff + minDiff(j + 1, daysRemaining - 1, jobDifficulty, mem));
}
mem[i][daysRemaining] = res;
return res;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 689. Maximum Sum of 3 Non-Overlapping Subarrays
Сложность: hard
Дан целочисленный массив nums и целое число k. Найдите три непересекающихся подмассива длины k с максимальной суммой и верните их.
Верните результат в виде списка индексов, представляющих начальную позицию каждого интервала (нумерация с 0). Если существует несколько ответов, верните лексикографически наименьший.
Пример:
👨💻 Алгоритм:
1⃣ Предположим, что фиксирован j. Нам нужно узнать на интервалах i∈[0,j−k] и l∈[j+k,len(W)−1], где наибольшее значение W[i] (и соответственно W[l]) встречается первым (то есть, с наименьшим индексом).
2⃣ Мы можем решить эту задачу с помощью динамического программирования. Например, если мы знаем, что i - это место, где наибольшее значение W[i] встречается первым на [0,5], то на [0,6] первое появление наибольшего W[i] должно быть либо i, либо 6. Если, скажем, 6 лучше, тогда мы устанавливаем best = 6. В конце left[z] будет первым вхождением наибольшего значения W[i] на интервале i∈[0,z], а right[z] будет таким же, но на интервале i∈[z,len(W)−1].
3⃣ Это означает, что для некоторого выбора j, кандидат на ответ должен быть (left[j - k], j, right[j + k]). Мы выбираем кандидата, который дает максимальное значение W[i] + W[j] + W[l].
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Дан целочисленный массив nums и целое число k. Найдите три непересекающихся подмассива длины k с максимальной суммой и верните их.
Верните результат в виде списка индексов, представляющих начальную позицию каждого интервала (нумерация с 0). Если существует несколько ответов, верните лексикографически наименьший.
Пример:
Input: nums = [1,2,1,2,6,7,5,1], k = 2
Output: [0,3,5]
Explanation: Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting indices [0, 3, 5].
We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically larger.
class Solution {
public:
vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
vector<int> W(nums.size() - k + 1);
int currSum = 0;
for (int i = 0; i < nums.size(); i++) {
currSum += nums[i];
if (i >= k) {
currSum -= nums[i - k];
}
if (i >= k - 1) {
W[i - k + 1] = currSum;
}
}
vector<int> left(W.size());
int best = 0;
for (int i = 0; i < W.size(); i++) {
if (W[i] > W[best]) best = i;
left[i] = best;
}
vector<int> right(W.size());
best = W.size() - 1;
for (int i = W.size() - 1; i >= 0; i--) {
if (W[i] >= W[best]) best = i;
right[i] = best;
}
vector<int> ans = {-1, -1, -1};
for (int j = k; j < W.size() - k; j++) {
int i = left[j - k], l = right[j + k];
if (ans[0] == -1 || W[i] + W[j] + W[l] > W[ans[0]] + W[ans[1]] + W[ans[2]]) {
ans = {i, j, l};
}
}
return ans;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 68. Text Justification
Сложность: hard
Дан массив слов words и ширина строки maxWidth. Необходимо вернуть текст, в котором строки выровнены по ширине с равномерным распределением пробелов, кроме последней строки — она выравнивается по левому краю.
Пример:
👨💻 Алгоритм:
1⃣ Разделить слова на строки: жадно добавлять слова, пока их суммарная длина + пробелы не превышают maxWidth
2⃣ Создать строку с выравниванием:
если последняя строка или в строке одно слово — выравниваем по левому краю
иначе: равномерно распределяем пробелы между словами, остаток пробелов добавляется слева
3⃣ Склеить строки и вернуть результат
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Дан массив слов words и ширина строки maxWidth. Необходимо вернуть текст, в котором строки выровнены по ширине с равномерным распределением пробелов, кроме последней строки — она выравнивается по левому краю.
Пример:
Input: words = ["This", "is", "an", "example", "of", "text", "justification."], maxWidth = 16
Output:
arduino[
"This is an",
"example of text",
"justification. "
]
если последняя строка или в строке одно слово — выравниваем по левому краю
иначе: равномерно распределяем пробелы между словами, остаток пробелов добавляется слева
class Solution {
public:
vector<string> fullJustify(vector<string>& words, int maxWidth) {
vector<string> ans;
int i = 0;
while (i < words.size()) {
vector<string> currentLine = getWords(i, words, maxWidth);
i += currentLine.size();
ans.push_back(createLine(currentLine, i, words, maxWidth));
}
return ans;
}
private:
vector<string> getWords(int i, vector<string>& words, int maxWidth) {
vector<string> currentLine;
int currLength = 0;
while (i < words.size() && currLength + words[i].size() <= maxWidth) {
currentLine.push_back(words[i]);
currLength += words[i].size() + 1;
i++;
}
return currentLine;
}
string createLine(vector<string>& line, int i, vector<string>& words, int maxWidth) {
int baseLength = -1;
for (const string& word : line) {
baseLength += word.size() + 1;
}
int extraSpaces = maxWidth - baseLength;
// Последняя строка или строка с одним словом
if (line.size() == 1 || i == words.size()) {
string res = join(line, " ");
res += string(extraSpaces, ' ');
return res;
}
int wordCount = line.size() - 1;
int spacesPerWord = extraSpaces / wordCount;
int needsExtraSpace = extraSpaces % wordCount;
for (int j = 0; j < needsExtraSpace; j++) {
line[j] += " ";
}
for (int j = 0; j < wordCount; j++) {
line[j] += string(spacesPerWord, ' ');
}
return join(line, " ");
}
string join(vector<string>& line, const string& delimeter) {
if (line.empty()) return "";
string res = line[0];
for (int i = 1; i < line.size(); i++) {
res += delimeter + line[i];
}
return res;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 244. Shortest Word Distance II
Сложность: medium
Необходимо реализовать структуру, которая быстро отвечает на запросы расстояния между двумя словами
Пример:
👨💻 Алгоритм:
1⃣ В конструкторе сохраняем словарь, где каждому слову сопоставляется список индексов, на которых оно встречается в массиве
2⃣ При запросе shortest(word1, word2) получаем два списка индексов и двигаемся по ним двумя указателями, считая минимальное расстояние
3⃣ Возвращаем минимальное абсолютное расстояние между индексами слов
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Необходимо реализовать структуру, которая быстро отвечает на запросы расстояния между двумя словами
Пример:
Input: ["WordDistance", "shortest", "shortest"] [[["practice", "makes", "perfect", "coding", "makes"]], ["coding", "practice"], ["makes", "coding"]] Output: [null, 3, 1]
#include <vector>
#include <string>
#include <unordered_map>
#include <algorithm>
class WordDistance {
public:
WordDistance(std::vector<std::string>& words) {
for (int i = 0; i < words.size(); ++i) {
locations[words[i]].push_back(i);
}
}
int shortest(std::string word1, std::string word2) {
const std::vector<int>& loc1 = locations[word1];
const std::vector<int>& loc2 = locations[word2];
int l1 = 0, l2 = 0, minDiff = INT_MAX;
while (l1 < loc1.size() && l2 < loc2.size()) {
minDiff = std::min(minDiff, std::abs(loc1[l1] - loc2[l2]));
if (loc1[l1] < loc2[l2]) {
++l1;
} else {
++l2;
}
}
return minDiff;
}
private:
std::unordered_map<std::string, std::vector<int>> locations;
};
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Задача: 476. Number Complement
Сложность: easy
Дополнение целого числа — это число, которое получается при замене всех 0 на 1 и всех 1 на 0 в его двоичном представлении.
Например, целое число 5 в двоичной системе — "101", и его дополнение — "010", что соответствует целому числу 2. Дано целое число num, верните его дополнение.
Пример:
👨💻 Алгоритм:
1⃣ Вычислите длину в битах входного числа: l=⌊log 2 (num)⌋+1.
2⃣ Постройте битовую маску из 1-битов длины l: bitmask=(1≪l)−1.
3⃣ Верните результат операции XOR числа и битовой маски: num⊕bitmask num⊕bitmask.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дополнение целого числа — это число, которое получается при замене всех 0 на 1 и всех 1 на 0 в его двоичном представлении.
Например, целое число 5 в двоичной системе — "101", и его дополнение — "010", что соответствует целому числу 2. Дано целое число num, верните его дополнение.
Пример:
Input: num = 5
Output: 2
Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2.
class Solution {
public:
int findComplement(int num) {
int bitmask = num;
bitmask |= (bitmask >> 1);
bitmask |= (bitmask >> 2);
bitmask |= (bitmask >> 4);
bitmask |= (bitmask >> 8);
bitmask |= (bitmask >> 16);
return bitmask ^ num;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 643. Maximum Average Subarray I
Сложность: easy
Вам дан целочисленный массив nums, состоящий из n элементов, и целое число k. Найдите смежный подмассив, длина которого равна k и который имеет максимальное среднее значение, и верните это значение. Принимается любой ответ с погрешностью вычислений менее 10-5.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация скользящего окна: Вычислите сумму первых k элементов массива nums. Это будет начальное значение максимальной суммы.
2⃣ Перемещение окна: Перемещайте окно длиной k по массиву, добавляя следующий элемент и убирая предыдущий, чтобы поддерживать сумму текущего окна.
3⃣ Обновление максимальной суммы: На каждом шаге обновляйте максимальную сумму, если текущая сумма больше, и в конце верните среднее значение этой суммы.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Вам дан целочисленный массив nums, состоящий из n элементов, и целое число k. Найдите смежный подмассив, длина которого равна k и который имеет максимальное среднее значение, и верните это значение. Принимается любой ответ с погрешностью вычислений менее 10-5.
Пример:
Input: nums = [1,12,-5,-6,50,3], k = 4
Output: 12.75000
class Solution {
public:
double findMaxAverage(vector<int>& nums, int k) {
int currentSum = accumulate(nums.begin(), nums.begin() + k, 0);
int maxSum = currentSum;
for (int i = k; i < nums.size(); i++) {
currentSum += nums[i] - nums[i - k];
maxSum = max(maxSum, currentSum);
}
return (double) maxSum / k;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 743. Network Delay Time
Сложность: medium
Дана сеть из узлов, помеченных от 1 до n. Также дано times - список времен прохождения сигнала в виде направленных ребер times[i] = (ui, vi, wi), где ui - исходный узел, vi - целевой узел, а wi - время прохождения сигнала от источника до цели. Мы пошлем сигнал из заданного узла k. Верните минимальное время, которое потребуется всем узлам, чтобы получить сигнал. Если все узлы не могут получить сигнал, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Представьте граф в виде списка смежности.
2⃣ Используйте алгоритм Дейкстры для нахождения кратчайших путей от узла k до всех других узлов.
3⃣ Найдите максимальное значение среди кратчайших путей к узлам. Если какой-либо узел недостижим, верните -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дана сеть из узлов, помеченных от 1 до n. Также дано times - список времен прохождения сигнала в виде направленных ребер times[i] = (ui, vi, wi), где ui - исходный узел, vi - целевой узел, а wi - время прохождения сигнала от источника до цели. Мы пошлем сигнал из заданного узла k. Верните минимальное время, которое потребуется всем узлам, чтобы получить сигнал. Если все узлы не могут получить сигнал, верните -1.
Пример:
Input: times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2
Output: 2
class Solution {
public:
int networkDelayTime(vector<vector<int>>& times, int n, int k) {
unordered_map<int, vector<pair<int, int>>> graph;
for (int i = 1; i <= n; ++i) {
graph[i] = vector<pair<int, int>>();
}
for (auto& time : times) {
graph[time[0]].emplace_back(time[1], time[2]);
}
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> minHeap;
minHeap.emplace(0, k);
unordered_map<int, int> minTime;
for (int i = 1; i <= n; ++i) {
minTime[i] = INT_MAX;
}
minTime[k] = 0;
while (!minHeap.empty()) {
auto [time, node] = minHeap.top(); minHeap.pop();
for (auto& [neighbor, t] : graph[node]) {
int newTime = time + t;
if (newTime < minTime[neighbor]) {
minTime[neighbor] = newTime;
minHeap.emplace(newTime, neighbor);
}
}
}
int maxTime = *max_element(minTime.begin(), minTime.end());
return maxTime == INT_MAX ? -1 : maxTime;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 96. Unique Binary Search Trees
Сложность: medium
Дано число n.
Нужно вычислить количество структурно уникальных бинарных деревьев поиска (BST),
состоящих из n узлов с уникальными значениями от 1 до n.
Пример:
👨💻 Алгоритм:
1⃣ Обозначим G(n) — количество уникальных BST, построенных из n узлов.
Пусть F(i, n) — количество BST, в которых i является корнем.
Тогда:
G(n) = F(1, n) + F(2, n) + ... + F(n, n)
2⃣ Для фиксированного i:
в левой части — i - 1 узел, в правой — n - i.
Т.е.
F(i, n) = G(i - 1) * G(n - i)
3⃣ Тогда:
G(n) = ∑ G(i - 1) * G(n - i), i = 1..n
Сохраняем значения G[0] = 1 и G[1] = 1, и далее строим по формуле.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дано число n.
Нужно вычислить количество структурно уникальных бинарных деревьев поиска (BST),
состоящих из n узлов с уникальными значениями от 1 до n.
Пример:
Input: n = 3
Output: 5
Пусть F(i, n) — количество BST, в которых i является корнем.
Тогда:
G(n) = F(1, n) + F(2, n) + ... + F(n, n)
в левой части — i - 1 узел, в правой — n - i.
Т.е.
F(i, n) = G(i - 1) * G(n - i)
G(n) = ∑ G(i - 1) * G(n - i), i = 1..n
Сохраняем значения G[0] = 1 и G[1] = 1, и далее строим по формуле.
class Solution {
public:
int numTrees(int n) {
vector<int> G(n + 1, 0);
G[0] = 1;
G[1] = 1;
for (int i = 2; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
G[i] += G[j - 1] * G[i - j];
}
}
return G[n];
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Задача: 1005. Maximize Sum Of Array After K Negations
Сложность: easy
Учитывая целочисленный массив nums и целое число k, измените массив следующим образом: выберите индекс i и замените nums[i] на -nums[i]. Вы должны применить этот процесс ровно k раз. Вы можете выбрать один и тот же индекс i несколько раз. Верните наибольшую возможную сумму массива после его модификации таким образом.
Пример:
👨💻 Алгоритм:
1⃣ Сортировка массива:
Отсортируйте массив nums по возрастанию, чтобы наибольшее количество раз менять самые маленькие (отрицательные) значения на их противоположные.
2⃣ Модификация массива:
Пройдитесь по отсортированному массиву и замените k наименьших значений на их противоположные (умножьте на -1). Если встретите 0, прекратите дальнейшие изменения, так как изменение 0 на -0 не имеет смысла.
3⃣ Проверка остатка изменений:
Если после первого прохода остались изменения (k нечетное), то найдите минимальное значение в измененном массиве и еще раз поменяйте его знак. Это обеспечит максимальную сумму.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Учитывая целочисленный массив nums и целое число k, измените массив следующим образом: выберите индекс i и замените nums[i] на -nums[i]. Вы должны применить этот процесс ровно k раз. Вы можете выбрать один и тот же индекс i несколько раз. Верните наибольшую возможную сумму массива после его модификации таким образом.
Пример:
Input: nums = [4,2,3], k = 1
Output: 5
Отсортируйте массив nums по возрастанию, чтобы наибольшее количество раз менять самые маленькие (отрицательные) значения на их противоположные.
Пройдитесь по отсортированному массиву и замените k наименьших значений на их противоположные (умножьте на -1). Если встретите 0, прекратите дальнейшие изменения, так как изменение 0 на -0 не имеет смысла.
Если после первого прохода остались изменения (k нечетное), то найдите минимальное значение в измененном массиве и еще раз поменяйте его знак. Это обеспечит максимальную сумму.
class Solution {
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); ++i) {
if (k > 0 && nums[i] < 0) {
nums[i] = -nums[i];
--k;
}
}
if (k % 2 == 1) {
sort(nums.begin(), nums.end());
nums[0] = -nums[0];
}
return accumulate(nums.begin(), nums.end(), 0);
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 1063. Number of Valid Subarrays
Сложность: hard
Дан целочисленный массив nums. Вернуть количество непустых подмассивов, в которых левый элемент не больше других элементов подмассива.
Подмассив — это непрерывная часть массива.
Пример:
👨💻 Алгоритм:
1⃣ нициализируйте переменную ans значением 0. Инициализируйте пустой стек st, который будет хранить индексы элементов в стеке.
2⃣ Итерируйте по элементам массива nums для каждого индекса i: продолжайте извлекать элементы из стека st, пока стек не станет пустым или элемент nums[i] не станет больше элемента на вершине стека. Для каждого извлеченного элемента добавляйте количество подмассивов как i - st.top(). Поместите текущий индекс i в стек.
3⃣ Извлеките все оставшиеся элементы из стека и для каждого рассмотрите размер nums как индекс следующего меньшего элемента. Соответственно, добавьте nums.size() - st.top() к переменной ans. Верните ans.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Дан целочисленный массив nums. Вернуть количество непустых подмассивов, в которых левый элемент не больше других элементов подмассива.
Подмассив — это непрерывная часть массива.
Пример:
Input: nums = [1,4,2,5,3]
Output: 11
Explanation: There are 11 valid subarrays: [1],[4],[2],[5],[3],[1,4],[2,5],[1,4,2],[2,5,3],[1,4,2,5],[1,4,2,5,3].
class Solution {
public:
int validSubarrays(vector<int>& nums) {
int ans = 0;
stack<int> st;
for (int i = 0; i < nums.size(); i++) {
while (!st.empty() && nums[i] < nums[st.top()]) {
ans += (i - st.top());
st.pop();
}
st.push(i);
}
while (!st.empty()) {
ans += (nums.size() - st.top());
st.pop();
}
return ans;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM