TGViewer
Channel Public Channel
C/C++ | LeetCode

C/C++ | LeetCode

@easy_c_plus_task

Сайт: https://easyoffer.ru/
Все каналы: t.me/+xGeAw6ckJ4liYzQy

Контакт для рекламы: @sendme_ads
Subscribers
3.23K
Photos
190
Videos
0
Links
1.5K

Showing posts older than #1963 · Back to latest

Older Posts 20 shown
Post #1962 272
Задача: 1049. Last Stone Weight II
Сложность: medium

Вам дан массив целых чисел stones, где stones[i] - вес i-го камня. Мы играем в игру с камнями. На каждом ходу мы выбираем два любых камня и разбиваем их вместе. Предположим, что камни имеют веса x и y, причем x <= y. Результат разбивания таков: если x == y, оба камня уничтожаются, а если x != y, камень веса x уничтожается, а камень веса y приобретает новый вес y - x. В конце игры остается не более одного камня. Верните наименьший возможный вес оставшегося камня. Если камней не осталось, верните 0.

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


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

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

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

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

😎 Решение:
class Solution {
public:
int lastStoneWeightII(vector<int>& stones) {
int totalSum = accumulate(stones.begin(), stones.end(), 0);
int halfSum = totalSum / 2;
vector<int> dp(halfSum + 1, 0);

for (int stone : stones) {
for (int j = halfSum; j >= stone; j--) {
dp[j] = max(dp[j], dp[j - stone] + stone);
}
}

return totalSum - 2 * dp[halfSum];
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1961 279
Задача: №27. Remove Element
Сложность: easy

Учитывая массив nums и значение val, удалите все вхождения val на месте. Порядок элементов может быть изменён. Верните количество элементов k, которые не равны val, и убедитесь, что первые k элементов массива содержат именно эти значения.

Пример:
Input: nums = [3,2,2,3], val = 3 Output: 2

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

1⃣Заводим указатель k для отслеживания позиции следующего "валидного" элемента.

2⃣Проходим по массиву: если текущий элемент не равен val, записываем его на позицию k и увеличиваем k.

3⃣После цикла k будет содержать количество элементов, не равных val.

😎 Решение:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int k = 0;
for(int i = 0; i < nums.size(); i++) {
if(nums[i] != val) {
nums[k] = nums[i];
k++;
}
}
return k;
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1960 289
Задача: 246. Strobogrammatic Number
Сложность: easy

Пример:
Input: num = "69"
Output: true

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

1⃣Пройдись по строке с конца, проверяя каждый символ на допустимость (0, 1, 6, 8, 9).

2⃣Построй перевёрнутую строку, заменяя 6 на 9 и наоборот.

3⃣Сравни перевёрнутую строку с исходной — если равны, значит число стробограмматическое.

😎 Решение:
#include <string>
using namespace std;

class Solution {
public:
bool isStrobogrammatic(string num) {
string rotated;
for (int i = num.length() - 1; i >= 0; i--) {
char c = num[i];
if (c == '0' || c == '1' || c == '8') {
rotated.push_back(c);
} else if (c == '6') {
rotated.push_back('9');
} else if (c == '9') {
rotated.push_back('6');
} else {
return false;
}
}
return num == rotated;
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1959 308
Задача: 1356. Sort Integers by The Number of 1 Bits
Сложность: easy

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

Верните массив после сортировки.

Пример:
Input: arr = [1024,512,256,128,64,32,16,8,4,2,1]
Output: [1,2,4,8,16,32,64,128,256,512,1024]
Explantion: All integers have 1 bit in the binary representation, you should just sort them in ascending order.


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

1⃣Создание функции для подсчета единиц:
Создайте функцию, которая принимает целое число и возвращает количество единиц в его двоичном представлении.

2⃣Сортировка массива:
Используйте встроенную функцию сортировки, передавая ей пользовательскую функцию сравнения, которая использует количество единиц в двоичном представлении чисел для сортировки. Если количество единиц одинаковое, используйте само число для сортировки.

3⃣Возврат отсортированного массива:
Верните отсортированный массив.

😎 Решение:
#include <vector>
#include <algorithm>

class Solution {
public:
std::vector<int> sortByBits(std::vector<int>& arr) {
std::sort(arr.begin(), arr.end(), [](int a, int b) {
int countA = __builtin_popcount(a);
int countB = __builtin_popcount(b);
return countA == countB ? a < b : countA < countB;
});
return arr;
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1958 322
Задача: 1165. Single-Row Keyboard
Сложность: easy

Есть специальная клавиатура, на которой все клавиши расположены в один ряд.

Дана строка keyboard длиной 26, указывающая на раскладку клавиатуры (индексирована от 0 до 25). Изначально ваш палец находится на индексе 0. Чтобы напечатать символ, нужно переместить палец на индекс нужного символа. Время, затраченное на перемещение пальца с индекса i на индекс j, равно |i - j|.

Вам нужно напечатать строку word. Напишите функцию для расчета времени, необходимого для её набора одним пальцем.

Пример:
Input: keyboard = "abcdefghijklmnopqrstuvwxyz", word = "cba"
Output: 4
Explanation: The index moves from 0 to 2 to write 'c' then to 1 to write 'b' then to 0 again to write 'a'.
Total time = 2 + 1 + 1 = 4.


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

1⃣Клавиатура содержит уникальные строчные английские буквы, поэтому мы можем сопоставить её с массивом размера 26. Создадим массив размера 26, назовём его keyIndices. Сохраните индекс каждой буквы в этом массиве, проходя по строке keyboard. Инициализируйте переменную result значением 0, которая будет хранить сумму всех расстояний. Объявите переменную prev, которая будет хранить индекс предыдущей клавиши. Поскольку начальная позиция равна 0, инициализируйте её значением 0.

2⃣Проходите по строке word буква за буквой. Для каждой буквы c добавьте ∣prev−indexOf(c)∣ к result. Обновите prev до индекса c.

3⃣Повторите шаги 6 и 7 для всех букв. В конце прохода result будет содержать итоговое время, необходимое для набора слова.

😎 Решение:
class Solution {
public:
int calculateTime(string keyboard, string word) {
vector<int> keyIndices(26, -1);
for (int i = 0; i < keyboard.length(); i++)
keyIndices[keyboard[i] - 'a'] = i;

int prev = 0;
int result = 0;

for (char &c : word) {
result += abs(prev - keyIndices[c - 'a']);
prev = keyIndices[c - 'a'];
}
return result;
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1956 356
Задача: 1044. Longest Duplicate Substring
Сложность: hard

Учитывая строку s, рассмотрите все дублированные подстроки: (смежные) подстроки s, которые встречаются 2 или более раз.Вхождения могут перекрываться. Верните любую дублированную подстроку, которая имеет наибольшую возможную длину.Если в s нет дублирующейся подстроки, ответом будет "".

Пример:
Input: s = "banana"
Output: "ana"


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

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

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

3⃣Хеширование с помощью функции rolling hash:
Rolling hash позволяет быстро вычислять хеши подстрок фиксированной длины и сравнивать их для поиска дубликатов.

😎 Решение:
string longestDupSubstring(string s) {
auto search = [&](int length) {
unordered_set<string> seen;
for (int i = 0; i <= s.size() - length; ++i) {
string sub = s.substr(i, length);
if (seen.count(sub)) {
return sub;
}
seen.insert(sub);
}
return string("");
};

int left = 1, right = s.size();
string result = "";
while (left < right) {
int mid = left + (right - left) / 2;
string dup = search(mid);
if (!dup.empty()) {
result = dup;
left = mid + 1;
} else {
right = mid;
}
}
return result;
}


Ставь 👍 и забирай 📚 Базу знаний
Post #1955 310
Завтра последний день!

Успей купить пожизненный easyoffer PRO - по цене 1 года

Покупаешь один раз — пользуешься всю жизнь.

👉 Акция до 31 марта: https://easyoffer.ru/pro
Post #1954 314
Задача: 320. Generalized Abbreviation
Сложность: medium

Обобщенная аббревиатура слова может быть построена путем замены любых неперекрывающихся и несмежных подстрок на их соответствующие длины.
Например, "abcde" можно сократить следующим образом:
"a3e" ("bcd" заменено на "3")
"1bcd1" ("a" и "e" заменены на "1")
"5" ("abcde" заменено на "5")
"abcde" (без замены подстрок)
Однако следующие аббревиатуры недействительны:
"23" ("ab" заменено на "2" и "cde" заменено на "3") недействительно, так как выбранные подстроки смежные.
"22de" ("ab" заменено на "2" и "bc" заменено на "2") недействительно, так как выбранные подстроки перекрываются.
Дано слово word, верните список всех возможных обобщенных аббревиатур слова. Верните ответ в любом порядке.

Пример:
Input: word = "a"
Output: ["1","a"]

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

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

2⃣Генерация аббревиатур
Для числа x просканируйте его бит за битом, чтобы определить, какие символы следует сохранить, а какие - сократить. Если бит равен 1, сохраните соответствующий символ, если 0 - замените его на счетчик.

3⃣Перебор всех комбинаций
Для каждого числа от 0 до 2^n - 1 используйте его битовое представление для создания соответствующей аббревиатуры. Сканируйте число x побитово, извлекая его последний бит с помощью b = x & 1 и сдвигая x вправо на один бит x >>= 1.

😎 Решение:
class Solution {
public:
vector<string> generateAbbreviations(string word) {
vector<string> ans;
for (int x = 0; x < (1 << word.length()); ++x)
ans.push_back(abbr(word, x));
return ans;
}

private:
string abbr(const string& word, int x) {
string builder;
int k = 0, n = word.length();
for (int i = 0; i < n; ++i, x >>= 1) {
if ((x & 1) == 0) {
if (k != 0) {
builder += to_string(k);
k = 0;
}
builder += word[i];
} else {
++k;
}
}
if (k != 0) builder += to_string(k);
return builder;
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1953 300
Задача: 1089. Duplicate Zeros
Сложность: easy

Дан массив целых чисел фиксированной длины arr, дублируйте каждое вхождение нуля, сдвигая оставшиеся элементы вправо.

Учтите, что элементы за пределами длины исходного массива не записываются. Внесите указанные изменения в массив на месте и ничего не возвращайте.

Пример:
Input: arr = [1,0,2,3,0,4,5,0]
Output: [1,0,0,2,3,0,0,4]
Explanation: After calling your function, the input array is modified to: [1,0,0,2,3,0,0,4]


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

1⃣Найдите количество нулей, которые будут продублированы, назовем это possible_dups. Необходимо убедиться, что мы не считаем нули, которые будут отброшены, так как отброшенные нули не будут частью итогового массива. Количество possible_dups даст нам количество элементов, которые будут отброшены из исходного массива. В любой момент времени length_ - possible_dups — это количество элементов, которые будут включены в итоговый массив.

2⃣Обработайте крайний случай для нуля, находящегося на границе оставшихся элементов. Будьте особенно внимательны при дублировании нулей в оставшемся массиве. Следует учитывать, лежит ли ноль на границе. Этот ноль может быть учтен с возможными дубликатами или может быть просто включен в оставшиеся элементы, когда не осталось места для его дубликата. Если он является частью possible_dups, мы хотим его дублировать, в противном случае — нет.

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

😎 Решение:
class Solution {
public:
void duplicateZeros(vector<int>& arr) {
int possibleDups = 0;
int length_ = arr.size() - 1;

for (int left = 0; left <= length_ - possibleDups; left++) {
if (arr[left] == 0) {
if (left == length_ - possibleDups) {
arr[length_] = 0;
length_ -= 1;
break;
}
possibleDups++;
}
}

int last = length_ - possibleDups;

for (int i = last; i >= 0; i--) {
if (arr[i] == 0) {
arr[i + possibleDups] = 0;
possibleDups--;
arr[i + possibleDups] = 0;
} else {
arr[i + possibleDups] = arr[i];
}
}
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1952 316
Задача: 1266. Minimum Time Visiting All Points
Сложность: easy

На двумерной плоскости имеется n точек с целочисленными координатами points[i] = [xi, yi]. Верните минимальное время в секундах для посещения всех точек в порядке, заданном точками. Вы можете перемещаться по следующим правилам: за 1 секунду вы можете либо: переместиться по вертикали на одну единицу, по горизонтали на одну единицу, либо по диагонали sqrt(2) единиц (другими словами, переместиться на одну единицу по вертикали и на одну единицу по горизонтали за 1 секунду). Вы должны посетить точки в том же порядке, в котором они появляются в массиве. Вы можете проходить через точки, которые появляются позже в порядке, но они не считаются за посещение.

Пример:
Input: points = [[1,1],[3,4],[-1,0]]
Output: 7


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

1⃣Инициализируйте переменную для хранения минимального времени.

2⃣Последовательно проходите по всем точкам и вычисляйте минимальное время для перехода от текущей точки к следующей.

3⃣Суммируйте время переходов для получения общего минимального времени.

😎 Решение:
class Solution {
public:
int minTimeToVisitAllPoints(vector<vector<int>>& points) {
int time = 0;
for (int i = 0; i < points.size() - 1; ++i) {
time += distance(points[i], points[i + 1]);
}
return time;
}

private:
int distance(vector<int>& p1, vector<int>& p2) {
return max(abs(p1[0] - p2[0]), abs(p1[1] - p2[1]));
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1951 304
Задача: 1229. Meeting Scheduler
Сложность: medium

Даны массивы доступных временных слотов slots1 и slots2 для двух человек и продолжительность встречи duration, верните самый ранний временной слот, который подходит обоим и имеет продолжительность duration.

Если нет общего временного слота, который удовлетворяет требованиям, верните пустой массив.

Формат временного слота — это массив из двух элементов [start, end], представляющий инклюзивный временной диапазон от start до end.

Гарантируется, что никакие два доступных временных слота одного и того же человека не пересекаются друг с другом. То есть для любых двух временных слотов [start1, end1] и [start2, end2] одного и того же человека либо start1 > end2, либо start2 > end1.

Пример:
Input: slots1 = [[10,50],[60,120],[140,210]], slots2 = [[0,15],[60,70]], duration = 8
Output: [60,68]


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

1⃣Отсортируйте оба массива slots1 и slots2 по времени начала.

2⃣Инициализируйте два указателя, указывающие на начало slots1 и slots2 соответственно.

3⃣Перебирайте, пока указатель1 не достигнет конца slots1 или указатель2 не достигнет конца slots2:
Найдите общий слот между slots1[pointer1] и slots2[pointer2].
Если общий слот больше или равен duration, верните результат.
В противном случае найдите слот, который заканчивается раньше, и передвиньте указатель.
Если общий слот не найден, верните пустой массив.

😎 Решение:
class Solution {
public:
vector<int> minAvailableDuration(vector<vector<int>>& slots1, vector<vector<int>>& slots2, int duration) {
sort(slots1.begin(), slots1.end());
sort(slots2.begin(), slots2.end());

int pointer1 = 0, pointer2 = 0;

while (pointer1 < slots1.size() && pointer2 < slots2.size()) {
int intersectLeft = max(slots1[pointer1][0], slots2[pointer2][0]);
int intersectRight = min(slots1[pointer1][1], slots2[pointer2][1]);

if (intersectRight - intersectLeft >= duration) {
return {intersectLeft, intersectLeft + duration};
}

if (slots1[pointer1][1] < slots2[pointer2][1]) {
pointer1++;
} else {
pointer2++;
}
}
return {};
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1950 334
Задача: 929. Unique Email Addresses
Сложность: easy

Вам дана сеть из n узлов, представленная в виде графа с матрицей смежности n x n, где i-й узел непосредственно связан с j-м узлом, если graph[i][j] == 1. Некоторые узлы изначально заражены вредоносным ПО. Если два узла соединены напрямую и хотя бы один из них заражен вредоносным ПО, то оба узла будут заражены вредоносным ПО. Такое распространение вредоносного ПО будет продолжаться до тех пор, пока больше не останется ни одного узла, зараженного таким образом. Предположим, что M(initial) - это конечное число узлов, зараженных вредоносным ПО, во всей сети после прекращения распространения вредоносного ПО. Мы удалим ровно один узел из initial, полностью удалив его и все связи от этого узла к любому другому узлу. Верните узел, который, если его удалить, минимизирует M(initial). Если для минимизации M(initial) можно удалить несколько узлов, верните такой узел с наименьшим индексом.

Пример:
Input: emails = ["test.email+alex@leetcode.com","test.e.mail+bob.cathy@leetcode.com","testemail+david@lee.tcode.com"]
Output: 2


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

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

2⃣Для каждого адреса в emails:
Разделить адрес на локальное и доменное имя по символу '@'.
Обработать локальное имя:
Удалить все точки '.'.
Обрезать часть после символа '+'.
Объединить обработанное локальное имя и доменное имя.
Добавить результат в множество уникальных адресов.

3⃣Вернуть количество уникальных адресов в множестве.

😎 Решение:
class Solution {
public int numUniqueEmails(String[] emails) {
Set<String> uniqueEmails = new HashSet<>();
for (String email : emails) {
String[] parts = email.split("@");
String local = parts[0].split("\\+")[0].replace(".", "");
uniqueEmails.add(local + "@" + parts[1]);
}
return uniqueEmails.size();
}
}


Ставь 👍 и забирай 📚 Базу знаний
Post #1948 323
Задача: 861. Score After Flipping Matrix
Сложность: medium

Вам дана бинарная матрица grid размером m x n.

Ход состоит из выбора любой строки или столбца и переключения каждого значения в этой строке или столбце (т.е. изменение всех 0 на 1, и всех 1 на 0).

Каждая строка матрицы интерпретируется как двоичное число, и счёт матрицы — это сумма этих чисел.

Верните наивысший возможный счёт после выполнения любого количества ходов (включая ноль ходов).

Пример:
Input: grid = [[0,0,1,1],[1,0,1,0],[1,1,0,0]]
Output: 39
Explanation: 0b1111 + 0b1001 + 0b1111 = 15 + 9 + 15 = 39


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

1⃣Инициализируйте переменные: m и n для количества строк и столбцов в grid, score для хранения максимального счёта матрицы. Пройдитесь по первому столбцу матрицы. Если элемент равен 0, переверните всю строку.

2⃣Пройдитесь по матрице от второго до последнего столбца. Для каждого столбца посчитайте количество нулей (countZero). Если количество нулей больше, переверните весь столбец.

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

😎 Решение:
class Solution {
public:
int matrixScore(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();

for (int i = 0; i < m; ++i) {
if (grid[i][0] == 0) {
for (int j = 0; j < n; ++j) {
grid[i][j] ^= 1;
}
}
}

for (int j = 1; j < n; ++j) {
int countZero = 0;
for (int i = 0; i < m; ++i) {
if (grid[i][j] == 0) {
countZero++;
}
}
if (countZero > m / 2) {
for (int i = 0; i < m; ++i) {
grid[i][j] ^= 1;
}
}
}

int score = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 1) {
score += 1 << (n - j - 1);
}
}
}

return score;
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1947 331
Задача: 32. Longest Valid Parentheses
Сложность: hard

Учитывая строку, содержащую только символы «(» и «)», верните длину самой длинной допустимой (правильно сформированной) подстроки скобок.

Пример:
Input: s = "(()" Output: 2

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

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

2⃣Проходим по строке: если '(', кладем индекс в стек, если ')' — извлекаем элемент.

3⃣Если после извлечения стек пуст — кладем текущий индекс, иначе — обновляем максимум длины как i - stack.top().

😎 Решение:
class Solution {
public:
int longestValidParentheses(string s) {
stack<int> stack;
int m = 0;
stack.push(-1);
for (int i = 0; i < s.length(); i++) {
if (s[i] == '(') {
stack.push(i);
} else {
stack.pop();
if (stack.empty()) {
stack.push(i);
} else {
m = max(m, (i - stack.top()));
}
}
}
return m;
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1946 302
Задача: 1102. Path With Maximum Minimum Value
Сложность: medium

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

Значение пути определяется минимальным числом на этом пути.

Пример:
Input: grid = [[5,4,5],[1,2,6],[7,4,6]]
Output: 4
Explanation: The path with the maximum score is highlighted in yellow.


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

1⃣Начните с оценки curScore = min(grid[0][0], grid[m-1][n-1]), где m и n - общее количество строк и столбцов входной матрицы.

2⃣Выполните BFS на матрице и проверьте, существует ли путь, где все значения больше или равны curScore:
Используйте очередь (deque) для хранения всех непосещенных ячеек со значением, большим или равным curScore.
Извлекайте ячейку из начала очереди, проверяйте, есть ли у нее непосещенные соседние ячейки, и добавляйте их в конец очереди.
Если успешно достигли правой нижней ячейки, значит путь существует.
Если очередь опустела до достижения правой нижней ячейки, пути не существует.

3⃣Если пути не существует, что означает, что curScore слишком велик, уменьшите его на 1 и повторите шаг 2.
В противном случае, верните curScore как ответ.

😎 Решение:
class Solution {
vector<vector<int>> dirs{{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
public:
int maximumMinimumPath(vector<vector<int>>& grid) {
int R = grid.size(), C = grid[0].size();
int curScore = min(grid[0][0], grid[R - 1][C - 1]);

while (curScore >= 0) {
if (pathExists(grid, curScore)) {
return curScore;
} else {
curScore--;
}
}
return -1;
}

bool pathExists(vector<vector<int>>& grid, int curScore) {
int R = grid.size(), C = grid[0].size();
vector<vector<bool>> visited(R, vector<bool>(C, false));
deque<pair<int, int>> dq{{0, 0}};
visited[0][0] = true;

auto push = [&](int row, int col) {
if (row >= 0 && col >= 0 && row < R && col < C && !visited[row][col] && grid[row][col] >= curScore) {
dq.push_back({row, col});
visited[row][col] = true;
}
};

while (!dq.empty()) {
int curRow = dq.front().first, curCol = dq.front().second;
dq.pop_front();
if (curRow == R - 1 && curCol == C - 1) {
return true;
}
for (auto dir : dirs) {
push(curRow + dir[0], curCol + dir[1]);
}
}
return false;
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1945 331
Задача: 502. IPO
Сложность: hard

Предположим, что LeetCode скоро начнет свое IPO. Чтобы продать свои акции по хорошей цене венчурным капиталистам, LeetCode хочет выполнить несколько проектов для увеличения своего капитала перед IPO. Поскольку у компании ограниченные ресурсы, она может завершить не более k различных проектов до IPO. Помогите LeetCode разработать лучший способ максимизации общего капитала после завершения не более k различных проектов.

Вам дано n проектов, где i-й проект имеет чистую прибыль profits[i] и требует минимального капитала capital[i] для его начала.

Изначально у вас есть капитал w. Когда вы завершаете проект, вы получаете его чистую прибыль, и эта прибыль добавляется к вашему общему капиталу.

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

Ответ гарантированно поместится в 32-битное целое число со знаком.

Пример:
Input: k = 2, w = 0, profits = [1,2,3], capital = [0,1,1]
Output: 4
Explanation: Since your initial capital is 0, you can only start the project indexed 0.
After finishing it you will obtain profit 1 and your capital becomes 1.
With capital 1, you can either start the project indexed 1 or the project indexed 2.
Since you can choose at most 2 projects, you need to finish the project indexed 2 to get the maximum capital.
Therefore, output the final maximized capital, which is 0 + 1 + 3 = 4.


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

1⃣Сортировка и инициализация
Отсортируйте проекты по возрастанию капитала. Создайте указатель ptr на первый недоступный проект в отсортированном массиве. Создайте приоритетную очередь для прибылей доступных проектов. Изначально очередь пуста.

2⃣Выбор проектов
Выполните следующие действия k раз: добавьте в приоритетную очередь прибыли новых доступных проектов. Перемещайте указатель по отсортированному массиву, когда проекты становятся доступными. Если приоритетная очередь пуста, завершите алгоритм.

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

😎 Решение:
class Solution {
public:
int findMaximizedCapital(int k, int w, vector<int>& profits, vector<int>& capital) {
vector<pair<int, int>> projects;
for (int i = 0; i < profits.size(); ++i) {
projects.emplace_back(capital[i], profits[i]);
}
sort(projects.begin(), projects.end());

priority_queue<int> maxHeap;
int ptr = 0;

for (int i = 0; i < k; ++i) {
while (ptr < projects.size() && projects[ptr].first <= w) {
maxHeap.push(projects[ptr].second);
ptr++;
}
if (maxHeap.empty()) break;
w += maxHeap.top();
maxHeap.pop();
}

return w;
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1944 322
Задача: 638. Shopping Offers
Сложность: medium

В магазине LeetCode Store есть n предметов для продажи. Каждый товар имеет свою цену. Однако существуют специальные предложения, и специальное предложение состоит из одного или нескольких различных видов товаров с распродажной ценой. Вам дан целочисленный массив price, где price[i] - цена i-го товара, и целочисленный массив needs, где needs[i] - количество штук i-го товара, который вы хотите купить. Вам также дан массив special, где special[i] имеет размер n + 1, где special[i][j] - количество штук j-го товара в i-м предложении, а special[i][n] (т.е., Возвращает наименьшую цену, которую вы можете заплатить за определенный товар из заданных, где вы могли бы оптимально использовать специальные предложения. Вам не разрешается покупать больше товаров, чем вы хотите, даже если это снизит общую цену. Вы можете использовать любое из специальных предложений столько раз, сколько захотите.

Пример:
Input: price = [2,5], special = [[3,0,5],[1,2,10]], needs = [3,2]
Output: 14

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

1⃣Рекурсивное вычисление стоимости: Определите функцию, которая рекурсивно вычисляет минимальную стоимость для оставшихся нужд, используя динамическое программирование для запоминания уже вычисленных значений.

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

3⃣Выбор минимальной стоимости: Сравните стоимость при использовании специальных предложений и стоимость при покупке товаров по индивидуальным ценам, выбирая минимальную стоимость.

😎 Решение:
class Solution {
public:
int shoppingOffers(vector<int>& price, vector<vector<int>>& special, vector<int>& needs) {
unordered_map<string, int> memo;
return dfs(price, special, needs, memo);
}

private:
int dfs(vector<int>& price, vector<vector<int>>& special, vector<int>& needs, unordered_map<string, int>& memo) {
string key = serialize(needs);
if (memo.find(key) != memo.end()) {
return memo[key];
}

int minPrice = 0;
for (int i = 0; i < needs.size(); i++) {
minPrice += needs[i] * price[i];
}

for (vector<int>& offer : special) {
vector<int> newNeeds(needs.size());
bool valid = true;
for (int i = 0; i < needs.size(); i++) {
if (needs[i] < offer[i]) {
valid = false;
break;
}
newNeeds[i] = needs[i] - offer[i];
}
if (valid) {
minPrice = min(minPrice, offer.back() + dfs(price, special, newNeeds, memo));
}
}

memo[key] = minPrice;
return minPrice;
}

string serialize(vector<int>& needs) {
string key = "";
for (int need : needs) {
key += to_string(need) + ",";
}
return key;
}
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1943 300
Задача: №30. Substring with Concatenation of All Words
Сложность: hard

Вам дана строка s и массив строк words, где все слова одинаковой длины. Найдите все стартовые индексы подстрок в s, которые являются конкатенацией всех слов из массива (в любом порядке, без дополнительных символов между ними).

Пример:
Input: s = "barfoothefoobarman", words = ["foo","bar"] Output: [0,9]

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

1⃣Вычисляем длину каждого слова и общее количество слов.

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

3⃣Отслеживаем, сколько раз каждое слово встречается, используя unordered_map.

😎 Решение:
vector<int> findSubstring(string str, vector<string>& words) {
int len = words[0].length();
unordered_map<string, int> contain;
for (string s : words) contain[s]++;

vector<int> res;
for (int j = 0; j < len; j++) {
unordered_map<string, int> found;
int st = j;
for (int i = j; i <= str.size() - len; i += len) {
string curr = str.substr(i, len);
if (contain.find(curr) != contain.end()) {
found[curr]++;
while (found[curr] > contain[curr]) {
found[str.substr(st, len)]--;
st += len;
}
int size = (i - st + len) / len;
if (size == words.size()) {
res.push_back(st);
}
} else {
found.clear();
st = i + len;
}
}
}
return res;
}


Ставь 👍 и забирай 📚 Базу знаний
Post #1942 296
Задача: 341. Flatten Nested List Iterator
Сложность: medium

Вам дан вложенный список целых чисел nestedList. Каждый элемент либо является целым числом, либо списком, элементы которого также могут быть целыми числами или другими списками. Реализуйте итератор для его развёртки.

Реализуйте класс NestedIterator:

NestedIterator(List<NestedInteger> nestedList) Инициализирует итератор вложенным списком nestedList.
int next() Возвращает следующий целый элемент вложенного списка.
boolean hasNext() Возвращает true, если в вложенном списке еще остались целые числа, и false в противном случае.

Пример:
Input: nestedList = [[1,1],2,[1,1]]
Output: [1,1,2,1,1]
Explanation: By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,1,2,1,1].


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

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

2⃣Метод next()
Возвращает следующий целый элемент из стека или очереди. Если текущий элемент является списком, развёртывайте его и добавляйте элементы в стек.

3⃣Метод hasNext()
Проверяет, есть ли в стеке или очереди оставшиеся целые элементы. Если на вершине стека находится список, развёртывайте его до тех пор, пока не встретится целый элемент.

😎 Решение:
class NestedIterator {
public:
NestedIterator(vector<NestedInteger> &nestedList) {
flatten(nestedList);
}

int next() {
return stack.back().getInteger();
}

bool hasNext() {
while (!stack.empty() && !stack.back().isInteger()) {
auto ni = stack.back();
stack.pop_back();
flatten(ni.getList());
}
return !stack.empty();
}

private:
void flatten(const vector<NestedInteger> &nestedList) {
for (auto it = nestedList.rbegin(); it != nestedList.rend(); ++it) {
stack.push_back(*it);
}
}

vector<NestedInteger> stack;
};


Ставь 👍 и забирай 📚 Базу знаний
Post #1941 301
Задача: 914. X of a Kind in a Deck of Cards
Сложность: easy

Вам дан целочисленный массив deck, где deck[i] - число, написанное на i-й карте. Разделите карты на одну или несколько групп так, чтобы: в каждой группе было ровно x карт, где x > 1, и на всех картах в одной группе было написано одно и то же целое число. Верните true, если такое разделение возможно, или false в противном случае.

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


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

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

2⃣Найти наибольший общий делитель (НОД) всех частот.

3⃣Проверить, больше ли НОД 1, чтобы определить, можно ли разделить карты на группы.

😎 Решение:
class Solution {
public:
bool hasGroupsSizeX(vector<int>& deck) {
unordered_map<int, int> count;
for (int num : deck) {
count[num]++;
}

int g = 0;
for (auto& [_, freq] : count) {
g = gcd(g, freq);
}

return g > 1;
}

private:
int gcd(int a, int b) {
while (b != 0) {
int temp = a % b;
a = b;
b = temp;
}
return a;
}
};


Ставь 👍 и забирай 📚 Базу знаний
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →