Задача: 361. Bomb Enemy
Сложность: medium
Дана матрица размером m x n, где каждая ячейка является либо стеной 'W', либо врагом 'E', либо пустой '0'. Верните максимальное количество врагов, которых можно уничтожить, используя одну бомбу. Вы можете разместить бомбу только в пустой ячейке.
Бомба уничтожает всех врагов в той же строке и столбце от точки установки до тех пор, пока не встретит стену, так как она слишком сильна, чтобы быть разрушенной.
Пример:
👨💻 Алгоритм:
1⃣ Перебрать каждую ячейку в сетке и для каждой пустой ячейки вычислить, сколько врагов можно убить, установив бомбу.
2⃣ Реализовать функцию killEnemies(row, col), которая считает количество врагов, убитых бомбой, установленных в пустой ячейке (row, col), проверяя все четыре направления (влево, вправо, вверх, вниз) до стены или границы сетки.
3⃣ Вернуть максимальное количество врагов, убитых среди всех пустых ячеек.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дана матрица размером m x n, где каждая ячейка является либо стеной 'W', либо врагом 'E', либо пустой '0'. Верните максимальное количество врагов, которых можно уничтожить, используя одну бомбу. Вы можете разместить бомбу только в пустой ячейке.
Бомба уничтожает всех врагов в той же строке и столбце от точки установки до тех пор, пока не встретит стену, так как она слишком сильна, чтобы быть разрушенной.
Пример:
Input: grid = [["0","E","0","0"],["E","0","W","E"],["0","E","0","0"]]
Output: 3
class Solution {
public:
int maxKilledEnemies(vector<vector<char>>& grid) {
if (grid.empty()) return 0;
int rows = grid.size();
int cols = grid[0].size();
int maxCount = 0;
for (int row = 0; row < rows; ++row) {
for (int col = 0; col < cols; ++col) {
if (grid[row][col] == '0') {
int hits = killEnemies(row, col, grid);
maxCount = max(maxCount, hits);
}
}
}
return maxCount;
}
private:
int killEnemies(int row, int col, vector<vector<char>>& grid) {
int enemyCount = 0;
vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for (const auto& dir : directions) {
int r = row + dir.first;
int c = col + dir.second;
while (r >= 0 && r < grid.size() && c >= 0 && c < grid[0].size()) {
if (grid[r][c] == 'W') break;
if (grid[r][c] == 'E') ++enemyCount;
r += dir.first;
c += dir.second;
}
}
return enemyCount;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 932. Beautiful Array
Сложность: medium
Массив nums длины n красив, если: nums является перестановкой целых чисел в диапазоне [1, n]. Для каждого 0 <= i < j < n не существует индекса k с i < k < j, где 2 * nums[k] == nums[i] + nums[j]. Задано целое число n, верните любой красивый массив nums длины n. Для заданного n будет хотя бы один правильный ответ.
Пример:
👨💻 Алгоритм:
1⃣ Использовать рекурсивный метод для создания красивого массива.
2⃣ Если длина массива равна 1, вернуть массив [1].
Разделить n на четные и нечетные индексы и создать массивы для них.
3⃣ Объединить массивы, созданные для четных и нечетных индексов, в результирующий массив.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Массив nums длины n красив, если: nums является перестановкой целых чисел в диапазоне [1, n]. Для каждого 0 <= i < j < n не существует индекса k с i < k < j, где 2 * nums[k] == nums[i] + nums[j]. Задано целое число n, верните любой красивый массив nums длины n. Для заданного n будет хотя бы один правильный ответ.
Пример:
Input: n = 4
Output: [2,1,4,3]
Разделить n на четные и нечетные индексы и создать массивы для них.
class Solution {
public:
vector<int> beautifulArray(int n) {
return construct(n);
}
private:
vector<int> construct(int n) {
if (n == 1) return {1};
vector<int> odd = construct((n + 1) / 2);
vector<int> even = construct(n / 2);
vector<int> result;
for (int x : odd) result.push_back(2 * x - 1);
for (int x : even) result.push_back(2 * x);
return result;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1436. Destination City
Сложность: easy
Дан массив paths, где paths[i] = [cityAi, cityBi] означает, что существует прямой путь из cityAi в cityBi. Вернуть конечный город, то есть город, из которого нет пути в другой город.
Гарантируется, что граф путей образует линию без циклов, поэтому будет ровно один конечный город.
Пример:
👨💻 Алгоритм:
1⃣ Для каждого города cityBi в paths проверьте, является ли он кандидатом на конечный город.
2⃣ Для каждого кандидата проверьте, нет ли пути, ведущего из него (cityAi == candidate).
3⃣ Верните город, который не имеет исходящих путей.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан массив paths, где paths[i] = [cityAi, cityBi] означает, что существует прямой путь из cityAi в cityBi. Вернуть конечный город, то есть город, из которого нет пути в другой город.
Гарантируется, что граф путей образует линию без циклов, поэтому будет ровно один конечный город.
Пример:
Input: paths = [["London","New York"],["New York","Lima"],["Lima","Sao Paulo"]]
Output: "Sao Paulo"
Explanation: Starting at "London" city you will reach "Sao Paulo" city which is the destination city. Your trip consist of: "London" -> "New York" -> "Lima" -> "Sao Paulo".
class Solution {
public:
string destCity(vector<vector<string>>& paths) {
for (auto& path : paths) {
string candidate = path[1];
bool good = true;
for (auto& p : paths) {
if (p[0] == candidate) {
good = false;
break;
}
}
if (good) {
return candidate;
}
}
return "";
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 202. Happy Number
Сложность: easy
Напишите алгоритм, определяющий, является ли число n счастливым.
Счастливое число — это такое число, которое в результате повторяющейся замены на сумму квадратов его цифр в конечном счёте становится равным 1.
Если процесс зацикливается и никогда не приводит к 1, число не является счастливым.
Пример:
👨💻 Алгоритм:
1⃣ Определяем функцию getNext(n), которая находит сумму квадратов всех цифр числа n.
2⃣ Используем HashSet, чтобы отслеживать уже встреченные числа. Если мы снова увидим уже встреченное число — значит, попали в цикл.
3⃣ Если на каком-то шаге число стало равным 1 — это счастливое число.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Напишите алгоритм, определяющий, является ли число n счастливым.
Счастливое число — это такое число, которое в результате повторяющейся замены на сумму квадратов его цифр в конечном счёте становится равным 1.
Если процесс зацикливается и никогда не приводит к 1, число не является счастливым.
Пример:
Input: n = 19 Output: true
Пояснение:
1² + 9² = 82
8² + 2² = 68
6² + 8² = 100
1² + 0² + 0² = 1 ✅
class Solution {
public:
int getNext(int n) {
int totalSum = 0;
while (n > 0) {
int digit = n % 10;
n = n / 10;
totalSum += digit * digit;
}
return totalSum;
}
bool isHappy(int n) {
unordered_set<int> seen;
while (n != 1 && seen.find(n) == seen.end()) {
seen.insert(n);
n = getNext(n);
}
return n == 1;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 19. Remove Nth Node From End of List
Сложность: medium
Учитывая заголовок связанного списка, удалите n-й узел с конца списка и верните его заголовок.
Пример:
👨💻 Алгоритм:
1⃣ Используем два указателя fast и slow, а также фиктивный узел перед головой для обработки краевых случаев.
2⃣ Сдвигаем fast на n шагов вперёд, чтобы создать нужную дистанцию.
3⃣ Затем двигаем fast и slow вместе до конца списка. Удаляем нужный узел, обновляя prev->next.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Учитывая заголовок связанного списка, удалите n-й узел с конца списка и верните его заголовок.
Пример:
Input: head = [1,2,3,4,5], n = 2
Output: [1,2,3,5]
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *slow = head, *fast = head;
ListNode *prev = new ListNode(0, head);
ListNode *answer = prev;
while (n > 1) {
fast = fast->next;
n--;
}
while (fast->next) {
fast = fast->next;
slow = slow->next;
prev = prev->next;
}
prev->next = slow->next;
return answer->next;
}
};
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 948. Bag of Tokens
Сложность: medium
Вы начинаете с начальной силой, равной power, начальным счетом 0 и мешком жетонов, представленным в виде целочисленного массива tokens, где каждый tokens[i] обозначает значение tokeni. Ваша цель - максимизировать общее количество очков, стратегически разыгрывая эти жетоны. За один ход вы можете разыграть неразыгранный жетон одним из двух способов (но не обоими для одного и того же жетона): лицом вверх: Если ваша текущая сила не меньше жетонов[i], вы можете сыграть токени, потеряв силу жетонов[i] и получив 1 очко. Лицом вниз: Если ваш текущий счет не меньше 1, вы можете сыграть токени, получив силу токенов[i] и потеряв 1 счет. Верните максимально возможный счет, который вы можете получить, сыграв любое количество токенов.
Пример:
👨💻 Алгоритм:
1⃣ Отсортировать массив tokens.
Использовать два указателя: left и right, чтобы отслеживать начало и конец массива токенов.
Инициализировать переменные для текущей силы power, текущего счета score и максимального счета maxScore
2⃣ Повторять следующие шаги, пока left не превысит right:
Если текущая сила power достаточна для разыгрывания токена tokens[left] лицом вверх, разыграть его и увеличить счет.
Если текущая сила недостаточна, но счет больше 0, разыграть токен tokens[right] лицом вниз и уменьшить счет.
Обновить максимальный счет, если текущий счет больше максимального.
3⃣ Вернуть максимальный счет.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вы начинаете с начальной силой, равной power, начальным счетом 0 и мешком жетонов, представленным в виде целочисленного массива tokens, где каждый tokens[i] обозначает значение tokeni. Ваша цель - максимизировать общее количество очков, стратегически разыгрывая эти жетоны. За один ход вы можете разыграть неразыгранный жетон одним из двух способов (но не обоими для одного и того же жетона): лицом вверх: Если ваша текущая сила не меньше жетонов[i], вы можете сыграть токени, потеряв силу жетонов[i] и получив 1 очко. Лицом вниз: Если ваш текущий счет не меньше 1, вы можете сыграть токени, получив силу токенов[i] и потеряв 1 счет. Верните максимально возможный счет, который вы можете получить, сыграв любое количество токенов.
Пример:
Input: tokens = [100], power = 50
Output: 0
Использовать два указателя: left и right, чтобы отслеживать начало и конец массива токенов.
Инициализировать переменные для текущей силы power, текущего счета score и максимального счета maxScore
Если текущая сила power достаточна для разыгрывания токена tokens[left] лицом вверх, разыграть его и увеличить счет.
Если текущая сила недостаточна, но счет больше 0, разыграть токен tokens[right] лицом вниз и уменьшить счет.
Обновить максимальный счет, если текущий счет больше максимального.
class Solution {
public:
int bagOfTokensScore(vector<int>& tokens, int power) {
sort(tokens.begin(), tokens.end());
int left = 0, right = tokens.size() - 1;
int score = 0, maxScore = 0;
while (left <= right) {
if (power >= tokens[left]) {
power -= tokens[left];
score++;
left++;
maxScore = max(maxScore, score);
} else if (score > 0) {
power += tokens[right];
score--;
right--;
} else {
break;
}
}
return maxScore;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 955. Delete Columns to Make Sorted II
Сложность: medium
Вам дан массив из n строк одинаковой длины. Мы можем выбрать любые индексы удаления и удалить все символы в этих индексах для каждой строки.
Например, если у нас есть strs = ["abcdef", "uvwxyz"] и индексы удаления {0, 2, 3}, то конечный массив после удаления будет ["bef", "vyz"]. Предположим, что мы выбрали набор индексов удаления answer таким образом, что после удаления конечный массив имеет элементы в лексикографическом порядке (т.е, strs[0] <= strs[1] <= strs[2] <= ... <= strs[n - 1]). Возвращает минимально возможное значение answer.length.
Пример:
👨💻 Алгоритм:
1⃣ Определить количество строк n и длину каждой строки m.
Создать массив delete_count длиной m, который будет отслеживать количество удаляемых столбцов.
2⃣ Итеративно проверить каждую пару соседних строк для всех столбцов.
Если для данной пары строк обнаружено нарушение лексикографического порядка, отметить соответствующий столбец для удаления.
3⃣ Повторять процесс до тех пор, пока массив строк не станет лексикографически отсортированным.
Вернуть количество удаленных столбцов.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан массив из n строк одинаковой длины. Мы можем выбрать любые индексы удаления и удалить все символы в этих индексах для каждой строки.
Например, если у нас есть strs = ["abcdef", "uvwxyz"] и индексы удаления {0, 2, 3}, то конечный массив после удаления будет ["bef", "vyz"]. Предположим, что мы выбрали набор индексов удаления answer таким образом, что после удаления конечный массив имеет элементы в лексикографическом порядке (т.е, strs[0] <= strs[1] <= strs[2] <= ... <= strs[n - 1]). Возвращает минимально возможное значение answer.length.
Пример:
Input: strs = ["ca","bb","ac"]
Output: 1
Создать массив delete_count длиной m, который будет отслеживать количество удаляемых столбцов.
Если для данной пары строк обнаружено нарушение лексикографического порядка, отметить соответствующий столбец для удаления.
Вернуть количество удаленных столбцов.
class Solution {
public:
int minDeletionSize(vector<string>& strs) {
int n = strs.size();
int m = strs[0].length();
vector<bool> deleteCount(m, false);
auto isSorted = [&]() {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < m; j++) {
if (deleteCount[j]) continue;
if (strs[i][j] > strs[i + 1][j]) return false;
if (strs[i][j] < strs[i + 1][j]) break;
}
}
return true;
};
while (!isSorted()) {
for (int j = 0; j < m; j++) {
if (deleteCount[j]) continue;
for (int i = 0; i < n - 1; i++) {
if (strs[i][j] > strs[i + 1][j]) {
deleteCount[j] = true;
break;
}
}
if (deleteCount[j]) break;
}
}
return count(deleteCount.begin(), deleteCount.end(), true);
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 44. Wildcard Matching
Сложность: hard
Дана входная строка s и шаблон p, реализуйте сопоставление с шаблоном с поддержкой символов:
? — соответствует любому одиночному символу
* — соответствует любой последовательности символов (включая пустую)
Сопоставление должно покрывать всю строку.
Пример:
👨💻 Алгоритм:
1⃣ Удалить дубликаты звёздочек (** → *), т.к. они не дают дополнительной информации
2⃣ Реализовать рекурсивную функцию helper, используя мемоизацию, чтобы избежать повторных вычислений
3⃣ Обрабатывать шаблон по следующим правилам:
Если p[i] == s[i] или p[i] == '?' → рекурсивно перейти к следующей паре
Если p[i] == '*' → два варианта: пропустить * или сопоставить с символом строки
Иначе — несовпадение
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Дана входная строка s и шаблон p, реализуйте сопоставление с шаблоном с поддержкой символов:
? — соответствует любому одиночному символу
* — соответствует любой последовательности символов (включая пустую)
Сопоставление должно покрывать всю строку.
Пример:
Input: s = "aa", p = "a" Output: false
Если p[i] == s[i] или p[i] == '?' → рекурсивно перейти к следующей паре
Если p[i] == '*' → два варианта: пропустить * или сопоставить с символом строки
Иначе — несовпадение
class Solution {
public:
unordered_map<string, bool> dp;
string p;
string s;
string remove_duplicate_stars(string p) {
string new_string = "";
for (auto &c : p) {
if (new_string.empty() || c != '*')
new_string += c;
else if (new_string.back() != '*')
new_string += c;
}
return new_string;
}
bool helper(int si, int pi) {
string key = to_string(si) + "," + to_string(pi);
if (dp.count(key)) return dp[key];
if (pi == p.size())
dp[key] = (si == s.size());
else if (si == s.size())
dp[key] = (pi + 1 == p.size() && p[pi] == '*');
else if (p[pi] == s[si] || p[pi] == '?')
dp[key] = helper(si + 1, pi + 1);
else if (p[pi] == '*')
dp[key] = helper(si, pi + 1) || helper(si + 1, pi);
else
dp[key] = false;
return dp[key];
}
bool isMatch(string s, string p) {
dp.clear();
this->s = s;
this->p = remove_duplicate_stars(p);
return helper(0, 0);
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 786. K-th Smallest Prime Fraction
Сложность: medium
Вам дан отсортированный массив целых чисел arr, содержащий 1 и простые числа, где все элементы массива arr уникальны. Также дано целое число k.
Для каждого i и j, где 0 <= i < j < arr.length, мы рассматриваем дробь arr[i] / arr[j].
Верните k-ую наименьшую дробь из рассмотренных. Верните ответ в виде массива из двух целых чисел размера 2, где answer[0] == arr[i] и answer[1] == arr[j].
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте пустую приоритетную очередь pq для хранения пар дробей и соответствующих им индексов. Итеративно пройдите по входному массиву arr, используя переменную цикла i. Для каждого элемента arr[i] вычислите дробь, образованную делением его на наибольший элемент в массиве (arr[arr.size() - 1]). Поместите пару, состоящую из отрицательного значения дроби (-1.0 * arr[i] / arr[arr.size() - 1]) и соответствующих индексов (i для числителя и arr.size() - 1 для знаменателя), в приоритетную очередь pq. Приоритетная очередь pq теперь содержит все дроби, образованные делением каждого элемента на наибольший элемент в массиве, отсортированные в порядке возрастания значений дробей.
2⃣ Повторите следующие шаги k - 1 раз: удалите верхний элемент (наименьшую дробь) из приоритетной очереди pq и сохраните его индексы в переменной cur. Уменьшите индекс знаменателя (cur[1]--). Вычислите новую дробь, образованную делением числителя в cur[0] на уменьшенный знаменатель (arr[cur[1]]). Поместите новое значение дроби (-1.0 * arr[cur[0]] / arr[cur[1]]) и соответствующие индексы (cur[0] для числителя и cur[1] для знаменателя) в приоритетную очередь pq. После k - 1 итераций верхний элемент приоритетной очереди pq будет k-й наименьшей дробью.
3⃣ Извлеките индексы числителя и знаменателя из верхнего элемента приоритетной очереди и сохраните их в result. Верните массив, содержащий значения числителя (arr[result[0]]) и знаменателя (arr[result[1]]), соответствующие k-й наименьшей дроби.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан отсортированный массив целых чисел arr, содержащий 1 и простые числа, где все элементы массива arr уникальны. Также дано целое число k.
Для каждого i и j, где 0 <= i < j < arr.length, мы рассматриваем дробь arr[i] / arr[j].
Верните k-ую наименьшую дробь из рассмотренных. Верните ответ в виде массива из двух целых чисел размера 2, где answer[0] == arr[i] и answer[1] == arr[j].
Пример:
Input: arr = [1,2,3,5], k = 3
Output: [2,5]
Explanation: The fractions to be considered in sorted order are:
1/5, 1/3, 2/5, 1/2, 3/5, and 2/3.
The third fraction is 2/5.
#include <queue>
#include <vector>
class Solution {
public:
std::vector<int> kthSmallestPrimeFraction(std::vector<int>& arr, int k) {
auto comp = [&arr](std::pair<int, int>& a, std::pair<int, int>& b) {
return arr[a.first] * arr[b.second] > arr[a.second] * arr[b.first];
};
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, decltype(comp)> pq(comp);
for (int i = 0; i < arr.size() - 1; i++) {
pq.emplace(i, arr.size() - 1);
}
for (int i = 0; i < k - 1; i++) {
auto [numeratorIndex, denominatorIndex] = pq.top();
pq.pop();
if (denominatorIndex - 1 > numeratorIndex) {
pq.emplace(numeratorIndex, denominatorIndex - 1);
}
}
auto [numeratorIndex, denominatorIndex] = pq.top();
return {arr[numeratorIndex], arr[denominatorIndex]};
}
};
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1268. Search Suggestions System
Сложность: medium
Вам дан массив строк products и строка searchWord. Разработайте систему, которая предлагает не более трех названий продуктов после ввода каждого символа searchWord. Предлагаемые товары должны иметь общий префикс с searchWord. Если есть более трех продуктов с общим префиксом, возвращаются три лексикографически минимальных продукта. Возвращается список списков предложенных продуктов после ввода каждого символа searchWord.
Пример:
👨💻 Алгоритм:
1⃣ Отсортируйте массив продуктов.
2⃣ Итерируйтесь по каждому символу в searchWord, находите все продукты, которые соответствуют текущему префиксу.
3⃣ Сохраняйте не более трех лексикографически минимальных продуктов для каждого префикса.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан массив строк products и строка searchWord. Разработайте систему, которая предлагает не более трех названий продуктов после ввода каждого символа searchWord. Предлагаемые товары должны иметь общий префикс с searchWord. Если есть более трех продуктов с общим префиксом, возвращаются три лексикографически минимальных продукта. Возвращается список списков предложенных продуктов после ввода каждого символа searchWord.
Пример:
Input: products = ["havana"], searchWord = "havana"
Output: [["havana"],["havana"],["havana"],["havana"],["havana"],["havana"]]
class Solution {
public:
vector<vector<string>> suggestedProducts(vector<string>& products, string searchWord) {
sort(products.begin(), products.end());
vector<vector<string>> result;
string prefix = "";
for (char c : searchWord) {
prefix += c;
vector<string> suggestions;
for (const string& product : products) {
if (product.find(prefix) == 0) {
suggestions.push_back(product);
if (suggestions.size() == 3) break;
}
}
result.push_back(suggestions);
}
return result;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Forwarded from Идущий к IT
🔥 Записал видос "Как за 3 минуты настроить Автоотклики на вакансии HeadHunter" больше не придется заниматься этой унылой рутиной
📺 Видео: https://youtu.be/G_FOwEGPwlw
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 437. Path Sum III
Сложность: medium
Дан корень бинарного дерева и целое число targetSum, вернуть количество путей, где сумма значений вдоль пути равна targetSum.
Путь не обязательно должен начинаться или заканчиваться в корне или на листе, но он должен идти вниз (т.е. перемещаться только от родительских узлов к дочерним).
Пример:
👨💻 Алгоритм:
1⃣ Инициализируем счетчик путей в дереве count = 0 и хеш-таблицу h, где ключ - это префиксная сумма, а значение - сколько раз она встречалась. Выполним рекурсивный обход дерева в порядке preorder: узел -> левый -> правый. Функция preorder(node: TreeNode, curr_sum: int) принимает два аргумента: узел дерева и префиксную сумму перед этим узлом. Чтобы запустить рекурсию, вызовем preorder(root, 0).
2⃣ Сначала обновим текущую префиксную сумму, добавив значение текущего узла: curr_sum += node.val. Теперь можно обновить счетчик. Рассмотрим две ситуации. В первой ситуации путь в дереве с целевой суммой начинается с корня. Это означает, что текущая префиксная сумма равна целевой сумме curr_sum == k, поэтому увеличиваем счетчик на 1: count += 1. Во второй ситуации путь с целевой суммой начинается где-то ниже. Это означает, что нужно добавить к счетчику количество раз, когда мы видели префиксную сумму curr_sum - target: count += h[curr_sum - target].
3⃣ Логика проста: текущая префиксная сумма - это curr_sum, а несколько элементов назад префиксная сумма была curr_sum - target. Все элементы между ними суммируются до curr_sum - (curr_sum - target) = target. Теперь обновим хеш-таблицу: h[curr_sum] += 1. Проанализируем левое и правое поддеревья: preorder(node.left, curr_sum), preorder(node.right, curr_sum). После обработки текущего поддерева удалим текущую префиксную сумму из хеш-таблицы, чтобы не смешивать параллельные поддеревья: h[curr_sum] -= 1. Когда обход в порядке preorder завершен, счетчик обновлен. Вернем его.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан корень бинарного дерева и целое число targetSum, вернуть количество путей, где сумма значений вдоль пути равна targetSum.
Путь не обязательно должен начинаться или заканчиваться в корне или на листе, но он должен идти вниз (т.е. перемещаться только от родительских узлов к дочерним).
Пример:
Input: root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
Output: 3
Explanation: The paths that sum to 8 are shown.
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
int count = 0;
int k = sum;
unordered_map<int, int> h;
preorder(root, 0, h, count, k);
return count;
}
void preorder(TreeNode* node, int curr_sum, unordered_map<int, int>& h, int& count, int k) {
if (!node) return;
curr_sum += node->val;
if (curr_sum == k) {
count++;
}
count += h[curr_sum - k];
h[curr_sum]++;
preorder(node->left, curr_sum, h, count, k);
preorder(node->right, curr_sum, h, count, k);
h[curr_sum]--;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 985. Sum of Even Numbers After Queries
Сложность: medium
Дан целочисленный массив nums и массив queries, где queries[i] = [vali, indexi].
Для каждого запроса i, сначала примените nums[indexi] = nums[indexi] + vali, затем выведите сумму четных значений nums.
Верните целочисленный массив answer, где answer[i] - это ответ на i-й запрос.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация переменных:
Завести переменную evenSum для хранения суммы всех четных чисел в массиве nums.
Пройти по массиву nums и вычислить начальное значение evenSum, сложив все четные числа в nums.
2⃣ Обработка запросов:
Создать пустой массив result для хранения ответов на каждый запрос.
Для каждого запроса [val, index] из массива queries выполнить следующие действия:
Если значение nums[index] четное, вычесть его из evenSum.
Обновить nums[index] добавлением val.
Если новое значение nums[index] четное, добавить его к evenSum.
Добавить текущее значение evenSum в массив result.
3⃣ Возврат результата:
Вернуть массив result, содержащий ответы на все запросы.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан целочисленный массив nums и массив queries, где queries[i] = [vali, indexi].
Для каждого запроса i, сначала примените nums[indexi] = nums[indexi] + vali, затем выведите сумму четных значений nums.
Верните целочисленный массив answer, где answer[i] - это ответ на i-й запрос.
Пример:
Input: nums = [1], queries = [[4,0]]
Output: [0]
Завести переменную evenSum для хранения суммы всех четных чисел в массиве nums.
Пройти по массиву nums и вычислить начальное значение evenSum, сложив все четные числа в nums.
Создать пустой массив result для хранения ответов на каждый запрос.
Для каждого запроса [val, index] из массива queries выполнить следующие действия:
Если значение nums[index] четное, вычесть его из evenSum.
Обновить nums[index] добавлением val.
Если новое значение nums[index] четное, добавить его к evenSum.
Добавить текущее значение evenSum в массив result.
Вернуть массив result, содержащий ответы на все запросы.
class Solution {
public:
vector<int> sumEvenAfterQueries(vector<int>& nums, vector<vector<int>>& queries) {
int evenSum = 0;
for (int num : nums) {
if (num % 2 == 0) {
evenSum += num;
}
}
vector<int> result;
for (const auto& query : queries) {
int val = query[0], index = query[1];
if (nums[index] % 2 == 0) {
evenSum -= nums[index];
}
nums[index] += val;
if (nums[index] % 2 == 0) {
evenSum += nums[index];
}
result.push_back(evenSum);
}
return result;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 968. Binary Tree Cameras
Сложность: hard
Вам дан корень бинарного дерева. Мы устанавливаем камеры на узлы дерева, где каждая камера на узле может наблюдать за своим родителем, собой и своими непосредственными детьми.
Верните минимальное количество камер, необходимых для наблюдения за всеми узлами дерева.
Пример:
👨💻 Алгоритм:
1⃣ Рекурсивное решение (solve):
Для каждого узла определите три состояния:
- [State 0] Строгое поддерево: все узлы ниже этого узла покрыты, но не сам узел.
- [State 1] Нормальное поддерево: все узлы ниже и включая этот узел покрыты, но на этом узле нет камеры.
- [State 2] Установленная камера: все узлы ниже и включая этот узел покрыты, и на этом узле установлена камера.
Рассчитайте эти состояния для левого и правого поддеревьев.
2⃣ Рассчёт состояний:
Чтобы покрыть строгое поддерево, дети этого узла должны находиться в состоянии 1.
Чтобы покрыть нормальное поддерево без установки камеры на этом узле, дети этого узла должны находиться в состояниях 1 или 2, и по крайней мере один из этих детей должен быть в состоянии 2.
Чтобы покрыть поддерево при установке камеры на этом узле, дети могут находиться в любом состоянии.
3⃣ Минимальное количество камер:
Запустите функцию solve на корневом узле и верните минимальное значение между состояниями 1 и 2.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Вам дан корень бинарного дерева. Мы устанавливаем камеры на узлы дерева, где каждая камера на узле может наблюдать за своим родителем, собой и своими непосредственными детьми.
Верните минимальное количество камер, необходимых для наблюдения за всеми узлами дерева.
Пример:
Input: root = [0,0,null,0,null,0,null,null,0]
Output: 2
Explanation: At least two cameras are needed to monitor all nodes of the tree. The above image shows one of the valid configurations of camera placement.
Для каждого узла определите три состояния:
- [State 0] Строгое поддерево: все узлы ниже этого узла покрыты, но не сам узел.
- [State 1] Нормальное поддерево: все узлы ниже и включая этот узел покрыты, но на этом узле нет камеры.
- [State 2] Установленная камера: все узлы ниже и включая этот узел покрыты, и на этом узле установлена камера.
Рассчитайте эти состояния для левого и правого поддеревьев.
Чтобы покрыть строгое поддерево, дети этого узла должны находиться в состоянии 1.
Чтобы покрыть нормальное поддерево без установки камеры на этом узле, дети этого узла должны находиться в состояниях 1 или 2, и по крайней мере один из этих детей должен быть в состоянии 2.
Чтобы покрыть поддерево при установке камеры на этом узле, дети могут находиться в любом состоянии.
Запустите функцию solve на корневом узле и верните минимальное значение между состояниями 1 и 2.
class Solution {
public:
int minCameraCover(TreeNode* root) {
int ans[3];
solve(root, ans);
return min(ans[1], ans[2]);
}
private:
void solve(TreeNode* node, int* res) {
if (!node) {
res[0] = res[1] = 0;
res[2] = 99999;
return;
}
int L[3], R[3];
solve(node->left, L);
solve(node->right, R);
res[0] = L[1] + R[1];
res[1] = min(L[2] + min(R[1], R[2]), R[2] + min(L[1], L[2]));
res[2] = 1 + min(L[0], min(L[1], L[2])) + min(R[0], min(R[1], R[2]));
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1481. Least Number of Unique Integers after K Removals
Сложность: medium
Дан массив целых чисел arr и целое число k. Найдите минимальное количество уникальных целых чисел после удаления ровно k элементов.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и построение частотного массива:
Создайте хеш-таблицу для отслеживания частот элементов массива arr.
Итеративно увеличивайте частоту элементов в хеш-таблице.
2⃣ Сортировка и удаление элементов:
Создайте массив частот и заполните его значениями из хеш-таблицы.
Отсортируйте массив частот.
Инициализируйте переменную для отслеживания числа удаленных элементов и итеративно добавляйте частоты, пока количество удаленных элементов не превысит k.
3⃣ Возвращение результата:
Если количество удаленных элементов превысило k, верните оставшееся количество уникальных элементов.
Если все элементы были удалены, верните 0.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив целых чисел arr и целое число k. Найдите минимальное количество уникальных целых чисел после удаления ровно k элементов.
Пример:
Input: arr = [5,5,4], k = 1
Output: 1
Explanation: Remove the single 4, only 5 is left.
Создайте хеш-таблицу для отслеживания частот элементов массива arr.
Итеративно увеличивайте частоту элементов в хеш-таблице.
Создайте массив частот и заполните его значениями из хеш-таблицы.
Отсортируйте массив частот.
Инициализируйте переменную для отслеживания числа удаленных элементов и итеративно добавляйте частоты, пока количество удаленных элементов не превысит k.
Если количество удаленных элементов превысило k, верните оставшееся количество уникальных элементов.
Если все элементы были удалены, верните 0.
class Solution {
public:
int findLeastNumOfUniqueInts(vector<int>& arr, int k) {
unordered_map<int, int> freqMap;
for (int num : arr) {
freqMap[num]++;
}
vector<int> frequencies;
for (auto& p : freqMap) {
frequencies.push_back(p.second);
}
sort(frequencies.begin(), frequencies.end());
int elementsRemoved = 0;
for (int i = 0; i < frequencies.size(); ++i) {
elementsRemoved += frequencies[i];
if (elementsRemoved > k) {
return frequencies.size() - i;
}
}
return 0;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Задача: 350. Intersection of Two Arrays II
Сложность: easy
Даны два целочисленных массива nums1 и nums2. Верните массив их пересечения. Каждый элемент в результате должен появляться столько раз, сколько он встречается в обоих массивах. Вы можете вернуть результат в любом порядке.
Пример:
👨💻 Алгоритм:
1⃣ Подсчет частоты элементов:
Используйте хеш-таблицу или словарь для подсчета количества вхождений каждого элемента в nums1.
2⃣ Нахождение пересечения:
Пройдите по элементам nums2, и если элемент присутствует в хеш-таблице из шага 1 и его счетчик больше нуля, добавьте этот элемент в результат и уменьшите счетчик.
3⃣ Возврат результата:
Верните массив пересечения.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Даны два целочисленных массива nums1 и nums2. Верните массив их пересечения. Каждый элемент в результате должен появляться столько раз, сколько он встречается в обоих массивах. Вы можете вернуть результат в любом порядке.
Пример:
Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2,2]
Используйте хеш-таблицу или словарь для подсчета количества вхождений каждого элемента в nums1.
Пройдите по элементам nums2, и если элемент присутствует в хеш-таблице из шага 1 и его счетчик больше нуля, добавьте этот элемент в результат и уменьшите счетчик.
Верните массив пересечения.
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
unordered_map<int, int> counts;
vector<int> result;
for (int num : nums1) {
counts[num]++;
}
for (int num : nums2) {
if (counts[num] > 0) {
result.push_back(num);
counts[num]--;
}
}
return result;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 754. Reach a Number
Сложность: medium
Вы стоите в позиции 0 на бесконечной числовой прямой. В позиции target находится пункт назначения. Вы можете сделать некоторое количество ходов numMoves так, чтобы: на каждом ходу вы могли пойти либо налево, либо направо. Во время i-го хода (начиная с i == 1 до i == numMoves) вы делаете i шагов в выбранном направлении. Учитывая целое число target, верните минимальное количество ходов (т.е. минимальное numMoves), необходимое для достижения пункта назначения.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте переменную для текущей позиции (position) и счетчик шагов (steps).
2⃣ Используйте цикл, чтобы добавлять к position текущее количество шагов и увеличивать steps.
3⃣ Если position достигает или превышает target и разница между position и target четная, остановите цикл и верните steps.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вы стоите в позиции 0 на бесконечной числовой прямой. В позиции target находится пункт назначения. Вы можете сделать некоторое количество ходов numMoves так, чтобы: на каждом ходу вы могли пойти либо налево, либо направо. Во время i-го хода (начиная с i == 1 до i == numMoves) вы делаете i шагов в выбранном направлении. Учитывая целое число target, верните минимальное количество ходов (т.е. минимальное numMoves), необходимое для достижения пункта назначения.
Пример:
Input: target = 2
Output: 3
class Solution {
public:
int reachTarget(int target) {
target = abs(target);
int position = 0;
int steps = 0;
while (position < target || (position - target) % 2 != 0) {
steps++;
position += steps;
}
return steps;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 116. Populating Next Right Pointers in Each Node
Сложность: medium
Дано идеальное бинарное дерево. Нужно установить next-указатели так, чтобы каждый узел указывал на своего соседа справа. Если соседа нет — указатель должен быть nullptr.
Пример:
👨💻 Алгоритм:
1⃣ Используем очередь (queue<Node*>) для обхода дерева в ширину (BFS). Начинаем с корня.
2⃣ На каждой итерации while, получаем size — количество узлов текущего уровня. Для всех узлов этого уровня:
Извлекаем узел из очереди.
Если это не последний узел уровня, устанавливаем node->next = Q.front().
Добавляем в очередь левого и правого потомков.
3⃣ Повторяем, пока очередь не пуста.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дано идеальное бинарное дерево. Нужно установить next-указатели так, чтобы каждый узел указывал на своего соседа справа. Если соседа нет — указатель должен быть nullptr.
Пример:
Input: root = [1,2,3,4,5,6,7] Output: [1,#,2,3,#,4,5,6,7,#]
Символ # означает конец уровня.
Извлекаем узел из очереди.
Если это не последний узел уровня, устанавливаем node->next = Q.front().
Добавляем в очередь левого и правого потомков.
class Solution {
public:
Node* connect(Node* root) {
if (root == nullptr) {
return root;
}
queue<Node*> Q;
Q.push(root);
while (!Q.empty()) {
int size = Q.size();
for (int i = 0; i < size; i++) {
Node* node = Q.front();
Q.pop();
if (i < size - 1) {
node->next = Q.front();
}
if (node->left != nullptr) {
Q.push(node->left);
}
if (node->right != nullptr) {
Q.push(node->right);
}
}
}
return root;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Айтишники, это вам — в телеграм есть комьюнити по каждому направлению в IT
Там есть буквально всё: чаты для общения, тонны материала(книги, курсы, ресурсы и гайды), свежие новости и конечно же мемы
Выбирайте своё направление:
💩 Frontend 🐍 Python
🐧 Linux 👩💻 С/С++
👩💻 C# 🤔 Хакинг & ИБ
📱 GitHub 🖥 SQL
👩💻 Сисадмин 🤟 DevOps
⚙️ Backend 🖥 Data Science
🧑💻 Java 🐞 Тестирование
🖥 PM / PdM 👩💻 GameDev
🧑💻 Golang 🤵♂️ IT-Митапы
🧑💻 PHP 💻 WebDev
🖥 Моб. Dev 🖥 Анали.(SA&BA)
👩💻 Дизайн 🖥 Нейросети
💛 1C 🤓 Книги IT
➡️ Сохраняйте в закладки
Там есть буквально всё: чаты для общения, тонны материала(книги, курсы, ресурсы и гайды), свежие новости и конечно же мемы
Выбирайте своё направление:
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 726. Number of Atoms
Сложность: hard
Если задана строковая формула, представляющая химическую формулу, верните количество атомов. Атомный элемент всегда начинается с прописного символа, затем ноль или более строчных букв, представляющих его название. Если количество больше 1, за ним может следовать одна или более цифр, представляющих количество элементов. Например, "H2O" и "H2O2" возможны, а "H1O2" невозможен. Две формулы объединяются вместе, чтобы получить другую формулу. Например, "H2O2He3Mg4" также является формулой.
Формула, заключенная в круглые скобки, и счет (по желанию) также являются формулами. Например, "(H2O2)" и "(H2O2)3" являются формулами.
Возвращает количество всех элементов в виде строки в следующем виде: первое имя (в отсортированном порядке), затем его количество (если это количество больше 1), затем второе имя (в отсортированном порядке), затем его количество (если это количество больше 1) и т. д. Тестовые примеры генерируются таким образом, чтобы все значения в выводе помещались в 32-битное целое число.
Пример:
👨💻 Алгоритм:
1⃣ Используйте стек для отслеживания текущего уровня скобок.
2⃣ Пройдите по строке формулы, анализируя каждый символ: Если символ - это открывающая скобка '(', создайте новый словарь для хранения атомов внутри скобок. Если символ - это закрывающая скобка ')', извлеките словарь из стека и умножьте количества атомов на последующее число, если оно присутствует. Если символ - это атом (начинается с заглавной буквы), извлеките имя атома и его количество, и добавьте его в текущий словарь.
3⃣ После завершения обработки строки, объедините все словари из стека и отсортируйте результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Если задана строковая формула, представляющая химическую формулу, верните количество атомов. Атомный элемент всегда начинается с прописного символа, затем ноль или более строчных букв, представляющих его название. Если количество больше 1, за ним может следовать одна или более цифр, представляющих количество элементов. Например, "H2O" и "H2O2" возможны, а "H1O2" невозможен. Две формулы объединяются вместе, чтобы получить другую формулу. Например, "H2O2He3Mg4" также является формулой.
Формула, заключенная в круглые скобки, и счет (по желанию) также являются формулами. Например, "(H2O2)" и "(H2O2)3" являются формулами.
Возвращает количество всех элементов в виде строки в следующем виде: первое имя (в отсортированном порядке), затем его количество (если это количество больше 1), затем второе имя (в отсортированном порядке), затем его количество (если это количество больше 1) и т. д. Тестовые примеры генерируются таким образом, чтобы все значения в выводе помещались в 32-битное целое число.
Пример:
Input: formula = "H2O"
Output: "H2O"
class Solution {
public:
string countOfAtoms(string formula) {
stack<map<string, int>> stack;
stack.push(map<string, int>());
int n = formula.size();
int i = 0;
while (i < n) {
if (formula[i] == '(') {
stack.push(map<string, int>());
i++;
} else if (formula[i] == ')') {
map<string, int> top = stack.top();
stack.pop();
i++;
int start = i;
while (i < n && isdigit(formula[i])) {
i++;
}
int multiplicity = i > start ? stoi(formula.substr(start, i - start)) : 1;
for (const auto& [name, count] : top) {
stack.top()[name] += count * multiplicity;
}
} else {
int start = i;
i++;
while (i < n && islower(formula[i])) {
i++;
}
string name = formula.substr(start, i - start);
start = i;
while (i < n && isdigit(formula[i])) {
i++;
}
int multiplicity = i > start ? stoi(formula.substr(start, i - start)) : 1;
stack.top()[name] += multiplicity;
}
}
map<string, int> countMap = stack.top();
string result;
for (const auto& [name, count] : countMap) {
result += name;
if (count > 1) {
result += to_string(count);
}
}
return result;
}
};Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
"Ты че, дурак?" – базовая реакция сеньора на тех, кто покупает IT курсы
Дело в том, что онлайн школы создают инкубаторных айтишников, которые в реальных условиях попросту зависнут.
Трушные ребята учатся на жизненных каналах для айтишников. Вот топ-5 от тимлида из Сбера:
⚙️ Технолоджия – для тех, кто хочет быть в курсе новостей в айти
🧠 Ai-чница – способы превратить нейросети в заработок $$$
💻 ИИ тебя заменит! – тенденции айти рынка в связке с нейросетями
4️⃣ Войти в IT – тонны бесплатного обучения для прогеров
😄 IT индус – сборник айти мемов
Дело в том, что онлайн школы создают инкубаторных айтишников, которые в реальных условиях попросту зависнут.
Трушные ребята учатся на жизненных каналах для айтишников. Вот топ-5 от тимлида из Сбера:
Please open Telegram to view this post
VIEW IN TELEGRAM