Java | LeetCode
6.98K subscribers
190 photos
1.12K links
Cайт easyoffer.ru
Реклама @easyoffer_adv
ВП @easyoffer_vp

Тесты t.iss.one/+icUwivvbGOkwNWRi
Вопросы собесов t.iss.one/+7ESm0VKXC4tjYzky
Вакансии t.iss.one/+4pspF5nDjgM4MjQy
Download Telegram
Задача: 1530. Number of Good Leaf Nodes Pairs
Сложность: medium

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

Верните количество хороших пар листовых узлов в дереве.

Пример:
Input: root = [1,2,3,null,4], distance = 3
Output: 1
Explanation: The leaf nodes of the tree are 3 and 4 and the length of the shortest path between them is 3. This is the only good pair.


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

1⃣Инициализируйте список смежности для преобразования дерева в граф и множество для хранения листовых узлов. Используйте вспомогательный метод traverseTree для обхода дерева, чтобы построить граф и найти листовые узлы. В параметрах поддерживайте текущий узел, а также родительский узел. Если текущий узел является листом, добавьте его в множество. В списке смежности добавьте текущий узел в список соседей родительского узла и наоборот. Рекурсивно вызовите traverseTree для левого и правого дочернего узла текущего узла.

2⃣Инициализируйте переменную ans для подсчета количества хороших пар листовых узлов. Итеративно переберите каждый листовой узел в множестве. Запустите BFS для текущего листового узла. BFS можно прервать досрочно, как только будут обнаружены все узлы, находящиеся на расстоянии от текущего листового узла. Увеличьте ans для каждого листового узла, найденного в каждом запуске BFS.

3⃣Верните ans / 2. Мы считаем каждую пару дважды, поэтому нужно разделить на 2, чтобы получить фактическое количество.

😎 Решение:
class Solution {

public int countPairs(TreeNode root, int distance) {
Map<TreeNode, List<TreeNode>> graph = new HashMap<>();
Set<TreeNode> leafNodes = new HashSet<>();
traverseTree(root, null, graph, leafNodes);
int ans = 0;
for (TreeNode leaf : leafNodes) {
Queue<TreeNode> bfsQueue = new LinkedList<>();
Set<TreeNode> seen = new HashSet<>();
bfsQueue.add(leaf);
seen.add(leaf);
for (int i = 0; i <= distance; i++) {
int size = bfsQueue.size();
for (int j = 0; j < size; j++) {
TreeNode currNode = bfsQueue.remove();
if (leafNodes.contains(currNode) && currNode != leaf) {
ans++;
}
if (graph.containsKey(currNode)) {
for (TreeNode neighbor : graph.get(currNode)) {
if (!seen.contains(neighbor)) {
bfsQueue.add(neighbor);
seen.add(neighbor);
}
}
}
}
}
}
return ans / 2;
}

private void traverseTree(
TreeNode currNode,
TreeNode prevNode,
Map<TreeNode, List<TreeNode>> graph,
Set<TreeNode> leafNodes
) {
if (currNode == null) {
return;
}
if (currNode.left == null && currNode.right == null) {
leafNodes.add(currNode);
}
if (prevNode != null) {
graph.computeIfAbsent(prevNode, k -> new ArrayList<TreeNode>());
graph.get(prevNode).add(currNode);
graph.computeIfAbsent(currNode, k -> new ArrayList<TreeNode>());
graph.get(currNode).add(prevNode);
}
traverseTree(currNode.left, currNode, graph, leafNodes);
traverseTree(currNode.right, currNode, graph, leafNodes);
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1064. Fixed Point
Сложность: easy

Дан массив различных целых чисел arr, отсортированный в порядке возрастания. Верните наименьший индекс i, который удовлетворяет условию arr[i] == i. Если такого индекса нет, верните -1.

Пример:
Input: arr = [-10,-5,0,3,7]
Output: 3
Explanation: For the given array, arr[0] = -10, arr[1] = -5, arr[2] = 0, arr[3] = 3, thus the output is 3.


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

1⃣Инициализируйте значение left как 0, right как N - 1 и answer как -1.

2⃣Пока размер области поиска не равен нулю, то есть left <= right, выполните следующие шаги: найдите mid как mid = (left + right) / 2. Сравните arr[mid] и mid: если arr[mid] = mid, сохраните mid в answer и перейдите в левую часть, изменив right на mid - 1; если arr[mid] < mid, перейдите в правую часть, изменив left на mid + 1; если arr[mid] > mid, перейдите в левую часть, изменив right на mid - 1.

3⃣Верните answer.

😎 Решение:
class Solution {
fun fixedPoint(arr: IntArray): Int {
var left = 0
var right = arr.size - 1
var answer = -1

while (left <= right) {
val mid = (left + right) / 2

if (arr[mid] == mid) {
answer = mid
right = mid - 1
} else if (arr[mid] < mid) {
left = mid + 1
} else {
right = mid - 1
}
}

return answer
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Задача: 739. Daily Temperatures
Сложность: medium

Задав массив целых чисел temperature, представляющих дневные температуры, верните массив answer, такой, что answer[i] - это количество дней, которые нужно подождать после i-го дня, чтобы температура стала теплее. Если в будущем не существует дня, для которого это возможно, сохраните answer[i] == 0.

Пример:
Input: temperatures = [73,74,75,71,69,72,76,73]
Output: [1,1,4,2,1,1,0,0]


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

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

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

3⃣Возвращайте массив ответов.

😎 Решение:
public class Solution {
public int[] dailyTemperatures(int[] T) {
int n = T.length;
int[] answer = new int[n];
Stack<Integer> stack = new Stack<>();

for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && T[i] > T[stack.peek()]) {
int j = stack.pop();
answer[j] = i - j;
}
stack.push(i);
}

return answer;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 968. Binary Tree Cameras
Сложность: 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.


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

1⃣Рекурсивное решение (solve):
Для каждого узла определите три состояния:
- [State 0] Строгое поддерево: все узлы ниже этого узла покрыты, но не сам узел.
- [State 1] Нормальное поддерево: все узлы ниже и включая этот узел покрыты, но на этом узле нет камеры.
- [State 2] Установленная камера: все узлы ниже и включая этот узел покрыты, и на этом узле установлена камера.
Рассчитайте эти состояния для левого и правого поддеревьев.

2⃣Рассчёт состояний:
Чтобы покрыть строгое поддерево, дети этого узла должны находиться в состоянии 1.
Чтобы покрыть нормальное поддерево без установки камеры на этом узле, дети этого узла должны находиться в состояниях 1 или 2, и по крайней мере один из этих детей должен быть в состоянии 2.
Чтобы покрыть поддерево при установке камеры на этом узле, дети могут находиться в любом состоянии.

3⃣Минимальное количество камер:
Запустите функцию solve на корневом узле и верните минимальное значение между состояниями 1 и 2.

😎 Решение:
class Solution {
public int minCameraCover(TreeNode root) {
int[] ans = solve(root);
return Math.min(ans[1], ans[2]);
}

public int[] solve(TreeNode node) {
if (node == null)
return new int[]{0, 0, 99999};

int[] L = solve(node.left);
int[] R = solve(node.right);
int mL12 = Math.min(L[1], L[2]);
int mR12 = Math.min(R[1], R[2]);

int d0 = L[1] + R[1];
int d1 = Math.min(L[2] + mR12, R[2] + mL12);
int d2 = 1 + Math.min(L[0], mL12) + Math.min(R[0], mR12);
return new int[]{d0, d1, d2};
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 296. Best Meeting Point
Сложность: hard

Дан бинарный сетка размером m x n, где каждая 1 обозначает дом одного друга. Верните минимальное общее расстояние путешествия.

Общее расстояние путешествия — это сумма расстояний между домами друзей и точкой встречи.

Расстояние рассчитывается по Манхэттенскому расстоянию, где distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|.

Пример:
Input: grid = [[1,0,0,0,1],[0,0,0,0,0],[0,0,1,0,0]]
Output: 6
Explanation: Given three friends living at (0,0), (0,4), and (2,2).
The point (0,2) is an ideal meeting point, as the total travel distance of 2 + 2 + 2 = 6 is minimal.
So return 6.


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

1⃣Определение координат домов:
Пройдите по сетке и соберите координаты всех домов (ячейки с значением 1) в два списка: один для координат x и один для координат y.

2⃣Нахождение медианы:
Отсортируйте списки координат x и y.
Найдите медианы в обоих списках. Медианы координат x и y укажут оптимальную точку встречи.

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

😎 Решение:
public class Solution {
public int minTotalDistance(int[][] grid) {
int minDistance = Integer.MAX_VALUE;
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid[0].length; col++) {
int distance = search(grid, row, col);
minDistance = Math.min(distance, minDistance);
}
}
return minDistance;
}

private int search(int[][] grid, int row, int col) {
Queue<int[]> q = new LinkedList<>();
q.add(new int[]{row, col, 0});
int m = grid.length;
int n = grid[0].length;
boolean[][] visited = new boolean[m][n];
int totalDistance = 0;

while (!q.isEmpty()) {
int[] point = q.poll();
int r = point[0];
int c = point[1];
int d = point[2];

if (r < 0 || c < 0 || r >= m || c >= n || visited[r][c]) {
continue;
}

if (grid[r][c] == 1) {
totalDistance += d;
}

visited[r][c] = true;

q.add(new int[]{r + 1, c, d + 1});
q.add(new int[]{r - 1, c, d + 1});
q.add(new int[]{r, c + 1, d + 1});
q.add(new int[]{r, c - 1, d + 1});
}

return totalDistance;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 438. Find All Anagrams in a String
Сложность: medium

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

Анаграмма - это слово или фраза, образованные перестановкой букв другого слова или фразы, обычно с использованием всех исходных букв ровно один раз.

Пример:
Input: s = "cbaebabacd", p = "abc"
Output: [0,6]
Explanation:
The substring with start index = 0 is "cba", which is an anagram of "abc".
The substring with start index = 6 is "bac", which is an anagram of "abc".


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

1⃣Построить эталонный счетчик pCount для строки p.

2⃣Передвигать скользящее окно по строке s: Пересчитывать счетчик скользящего окна sCount на каждом шаге, добавляя одну букву справа и удаляя одну букву слева.

3⃣Если sCount == pCount, обновить выходной список. Вернуть выходной список.

😎 Решение:
class Solution {
public List<Integer> findAnagrams(String s, String p) {
int ns = s.length(), np = p.length();
if (ns < np) return new ArrayList<>();

Map<Character, Integer> pCount = new HashMap<>();
Map<Character, Integer> sCount = new HashMap<>();

for (char ch : p.toCharArray()) {
pCount.put(ch, pCount.getOrDefault(ch, 0) + 1);
}

List<Integer> output = new ArrayList<>();

for (int i = 0; i < ns; ++i) {
char ch = s.charAt(i);
sCount.put(ch, sCount.getOrDefault(ch, 0) + 1);

if (i >= np) {
ch = s.charAt(i - np);
if (sCount.get(ch) == 1) {
sCount.remove(ch);
} else {
sCount.put(ch, sCount.get(ch) - 1);
}
}

if (pCount.equals(sCount)) {
output.add(i - np + 1);
}
}
return output;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Задача: 220. Contains Duplicate III
Сложность: hard

Вам дан массив целых чисел nums и два целых числа indexDiff и valueDiff.

Найдите пару индексов (i, j) таких, что:
i != j,
abs(i - j) <= indexDiff,
abs(nums[i] - nums[j]) <= valueDiff.

Верните true, если такая пара существует, или false в противном случае.

Пример:
Input: nums = [1,2,3,1], indexDiff = 3, valueDiff = 0
Output: true
Explanation: We can choose (i, j) = (0, 3).
We satisfy the three conditions:
i != j --> 0 != 3
abs(i - j) <= indexDiff --> abs(0 - 3) <= 3
abs(nums[i] - nums[j]) <= valueDiff --> abs(1 - 1) <= 0


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

1⃣Инициализация и вычисление корзин:
Рассчитать ширину корзины w = t + 1.
Инициализировать пустой хэш-таблицей buckets.
Определить функцию getID, которая возвращает идентификатор корзины для элемента x и ширины корзины w.

2⃣Итерация и проверка корзин:
Перебрать все элементы массива nums.
Для каждого элемента nums[i]:
Определить его корзину с помощью getID.
Проверить, есть ли в текущей корзине элемент. Если есть, вернуть true.
Проверить соседние корзины на наличие "почти дубликатов". Если есть, вернуть true.
Если текущая корзина пуста и в соседних корзинах нет "почти дубликатов", добавить текущий элемент в соответствующую корзину.
Если текущий индекс превышает k, удалить элемент из корзины, которая вышла за пределы окна.

3⃣Завершение:
Если ни одна пара "почти дубликатов" не найдена, вернуть false.

😎 Решение:
class Solution {
private long getID(long x, long w) {
return Math.floorDiv(x, w);
}

public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
if (t < 0) return false;
Map<Long, Long> buckets = new HashMap<>();
long w = (long) t + 1;
for (int i = 0; i < nums.length; ++i) {
long bucket = getID(nums[i], w);
if (buckets.containsKey(bucket)) return true;
if (
buckets.containsKey(bucket - 1) &&
Math.abs(nums[i] - buckets.get(bucket - 1)) < w
) return true;
if (
buckets.containsKey(bucket + 1) &&
Math.abs(nums[i] - buckets.get(bucket + 1)) < w
) return true;
buckets.put(bucket, (long) nums[i]);
if (i >= k) buckets.remove(getID(nums[i - k], w));
}
return false;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 318. Maximum Product of Word Lengths
Сложность: medium

Дан массив строк words, верните максимальное значение произведения длины word[i] на длину word[j], где два слова не имеют общих букв. Если таких двух слов не существует, верните 0.

Пример:
Input: words = ["abcw","baz","foo","bar","xtfn","abcdef"]
Output: 16
Explanation: The two words can be "abcw", "xtfn".


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

1⃣Предварительная обработка масок и длин
Вычислите битовые маски для всех слов и сохраните их в массиве masks. Сохраните длины всех слов в массиве lens.

2⃣Сравнение слов и проверка общих букв
Сравните каждое слово с каждым последующим словом. Если два слова не имеют общих букв (проверка с использованием масок: (masks[i] & masks[j]) == 0), обновите максимальное произведение maxProd.

3⃣Возврат результата
Верните максимальное значение произведения maxProd.

😎 Решение:
class Solution {
public int maxProduct(String[] words) {
int n = words.length;
int[] masks = new int[n];
int[] lens = new int[n];

for (int i = 0; i < n; i++) {
int bitmask = 0;
for (char ch : words[i].toCharArray()) {
bitmask |= 1 << (ch - 'a');
}
masks[i] = bitmask;
lens[i] = words[i].length();
}

int maxVal = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if ((masks[i] & masks[j]) == 0) {
maxVal = Math.max(maxVal, lens[i] * lens[j]);
}
}
}
return maxVal;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: №43. Multiply Strings
Сложность: medium

Учитывая два неотрицательных целых числа num1 и num2, представленных в виде строк, верните их произведение, также в виде строки.
*Нельзя использовать встроенные библиотеки BigInteger или преобразовывать строки напрямую в числа.*

Пример:
Input: num1 = "123", num2 = "456" Output: "56088"


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

1⃣Создаём массив pos длиной m + n (где m и n — длины num1 и num2) для хранения промежуточных результатов поразрядного умножения.

2⃣Проходим в обратном порядке по каждой цифре num1 и num2, перемножаем и сохраняем результат в pos с учётом разрядов (p1, p2), добавляя переносы в старшие разряды.

3⃣Преобразуем массив pos в строку, пропуская ведущие нули.

😎 Решение:
public String multiply(String num1, String num2) {
int m = num1.length(), n = num2.length();
int[] pos = new int[m + n];

for(int i = m - 1; i >= 0; i--) {
for(int j = n - 1; j >= 0; j--) {
int mul = (num1.charAt(i) - '0') * (num2.charAt(j) - '0');
int p1 = i + j, p2 = i + j + 1;
int sum = mul + pos[p2];

pos[p1] += sum / 10;
pos[p2] = sum % 10;
}
}

StringBuilder sb = new StringBuilder();
for (int p : pos)
if (!(sb.length() == 0 && p == 0)) sb.append(p);

return sb.length() == 0 ? "0" : sb.toString();
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 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-й запрос.

Пример:
Input: nums = [1], queries = [[4,0]]
Output: [0]


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

1⃣Инициализация переменных:
Завести переменную evenSum для хранения суммы всех четных чисел в массиве nums.
Пройти по массиву nums и вычислить начальное значение evenSum, сложив все четные числа в nums.

2⃣Обработка запросов:
Создать пустой массив result для хранения ответов на каждый запрос.
Для каждого запроса [val, index] из массива queries выполнить следующие действия:
Если значение nums[index] четное, вычесть его из evenSum.
Обновить nums[index] добавлением val.
Если новое значение nums[index] четное, добавить его к evenSum.
Добавить текущее значение evenSum в массив result.

3⃣Возврат результата:
Вернуть массив result, содержащий ответы на все запросы.

😎 Решение:
public class Solution {
public int[] sumEvenAfterQueries(int[] nums, int[][] queries) {
int evenSum = 0;
for (int num : nums) {
if (num % 2 == 0) {
evenSum += num;
}
}

int[] result = new int[queries.length];
for (int i = 0; i < queries.length; i++) {
int val = queries[i][0], index = queries[i][1];
if (nums[index] % 2 == 0) {
evenSum -= nums[index];
}
nums[index] += val;
if (nums[index] % 2 == 0) {
evenSum += nums[index];
}
result[i] = evenSum;
}

return result;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 60. Permutation Sequence
Сложность: hard

Множество [1, 2, 3, ..., n] содержит в общей сложности n! уникальных перестановок.

Списком и маркировкой всех перестановок по порядку, мы получаем следующую последовательность для n = 3:

"123"
"132"
"213"
"231"
"312"
"321"
Дано n и k, верните k-ю перестановку последовательности.

Пример:
Input: n = 3, k = 3
Output: "213"


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

1⃣Сгенерируйте входной массив nums чисел от 1 до N.

2⃣Вычислите все факториальные основы от 0 до (N−1)!.

3⃣Уменьшите k на 1, чтобы значение попало в интервал (0, N!−1). Используйте коэффициенты факториалов для построения перестановки. Верните строку перестановки.

😎 Решение:
class Solution {
public String getPermutation(int n, int k) {
int[] factorials = new int[n];
List<Integer> nums = new ArrayList() {{
add(1);
}};

factorials[0] = 1;
for (int i = 1; i < n; ++i) {
factorials[i] = factorials[i - 1] * i;
nums.add(i + 1);
}

--k;

StringBuilder sb = new StringBuilder();
for (int i = n - 1; i > -1; --i) {
int idx = k / factorials[i];
k -= idx * factorials[i];

sb.append(nums.get(idx));
nums.remove(idx);
}
return sb.toString();
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 88. Merge Sorted Array
Сложность: easy

Вам даны два массива целых чисел nums1 и nums2, отсортированных в порядке неубывания, а также два целых числа m и n, представляющих количество элементов в nums1 и nums2 соответственно.

Слейте nums1 и nums2 в один массив, отсортированный в порядке неубывания.

Итоговый отсортированный массив не должен возвращаться функцией, а должен храниться внутри массива nums1. Чтобы это обеспечить, длина nums1 составляет m + n, где первые m элементов обозначают элементы, которые должны быть объединены, а последние n элементов установлены в 0 и должны быть проигнорированы. Длина nums2 составляет n.

Пример:
Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
Explanation: The arrays we are merging are [1,2,3] and [2,5,6].
The result of the merge is [1,2,2,3,5,6] with the underlined elements coming from nums1.


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

1⃣Самая простая реализация заключалась бы в создании копии значений в nums1, называемой nums1Copy, а затем использовании двух указателей для чтения и одного указателя для записи для чтения значений из nums1Copy и nums2 и записи их в nums1.

2⃣Инициализируйте nums1Copy новым массивом, содержащим первые m значений nums1.
Инициализируйте указатель для чтения p1 в начале nums1Copy.
Инициализируйте указатель для чтения p2 в начале nums2.

3⃣Инициализируйте указатель для записи p в начале nums1.
Пока p все еще находится внутри nums1:
Если nums1Copy[p1] существует и меньше или равно nums2[p2]:
Запишите nums1Copy[p1] в nums1[p], и увеличьте p1 на 1.
Иначе
Запишите nums2[p2] в nums1[p], и увеличьте p2 на 1.
Увеличьте p на 1.

😎 Решение:
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int[] nums1Copy = new int[m];
for (int i = 0; i < m; i++) {
nums1Copy[i] = nums1[i];
}
int p1 = 0;
int p2 = 0;
for (int p = 0; p < m + n; p++) {
if (p2 >= n || (p1 < m && nums1Copy[p1] < nums2[p2])) {
nums1[p] = nums1Copy[p1++];
} else {
nums1[p] = nums2[p2++];
}
}
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1💊1
Задача: 735. Asteroid Collision
Сложность: medium

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

Пример:
Input: sentence1 = ["great","acting","skills"], sentence2 = ["fine","drama","talent"], similarPairs = [["great","fine"],["drama","acting"],["skills","talent"]]
Output: true


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

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

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

3⃣Добавьте оставшиеся астероиды из стека и текущий астероид в результат.

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

public class Solution {
public int[] asteroidCollision(int[] asteroids) {
Stack<Integer> stack = new Stack<>();

for (int asteroid : asteroids) {
boolean alive = true;
while (alive && asteroid < 0 && !stack.isEmpty() && stack.peek() > 0) {
int last = stack.pop();
if (last == -asteroid) {
alive = false;
} else if (last > -asteroid) {
stack.push(last);
alive = false;
}
}
if (alive) {
stack.push(asteroid);
}
}

int[] result = new int[stack.size()];
for (int i = result.length - 1; i >= 0; i--) {
result[i] = stack.pop();
}

return result;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 761. Special Binary String
Сложность: hard

Специальные двоичные строки - это двоичные строки, обладающие следующими двумя свойствами: количество 0 равно количеству 1. Каждый префикс двоичной строки имеет не меньше 1, чем 0. Вам дана специальная двоичная строка s. Ход состоит в выборе двух последовательных, непустых специальных подстрок s и их обмене. Две строки являются последовательными, если последний символ первой строки находится ровно на один индекс раньше первого символа второй строки. Верните лексикографически наибольшую результирующую строку, возможную после применения указанных операций над строкой.

Пример:
Input: s = "11011000"
Output: "11100100"


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

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

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

3⃣Сортируйте полученные подстроки в лексикографическом порядке по убыванию и объединяйте их.

😎 Решение:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Solution {
public String makeLargestSpecial(String s) {
int count = 0, i = 0;
List<String> substrs = new ArrayList<>();
for (int j = 0; j < s.length(); j++) {
count += s.charAt(j) == '1' ? 1 : -1;
if (count == 0) {
substrs.add("1" + makeLargestSpecial(s.substring(i + 1, j)) + "0");
i = j + 1;
}
}
Collections.sort(substrs, Collections.reverseOrder());
return String.join("", substrs);
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Cтажировки и вакансии для JAVA разработчиков.

- Вакансии которых нет на джоб-агрегаторах
- Только прямые контакты HR в Telegram

👉 @jobs_java

Пока другие листают джоб-сайты — ты уже пишешь HR в Telegram.
Задача: 965. Univalued Binary Tree
Сложность: medium

Дан список слов, и нам нужно реализовать проверку орфографии, которая преобразует слово запроса в правильное слово.

Для данного слова запроса, проверка орфографии обрабатывает две категории ошибок правописания:
Заглавные буквы: если запрос совпадает со словом в списке слов (без учета регистра), то слово запроса возвращается с таким же регистром, как и в списке слов.
Пример: wordlist = ["yellow"], query = "YellOw": correct = "yellow"
Пример: wordlist = ["Yellow"], query = "yellow": correct = "Yellow"
Пример: wordlist = ["yellow"], query = "yellow": correct = "yellow"

Ошибки гласных: если после замены гласных ('a', 'e', 'i', 'o', 'u') в слове запроса на любую гласную по отдельности оно совпадает со словом в списке слов (без учета регистра), то слово запроса возвращается с таким же регистром, как и совпадающее слово в списке слов.
Пример: wordlist = ["YellOw"], query = "yollow": correct = "YellOw"
Пример: wordlist = ["YellOw"], query = "yeellow": correct = "" (нет совпадения)
Пример: wordlist = ["YellOw"], query = "yllw": correct = "" (нет совпадения)

Кроме того, проверка орфографии работает по следующим правилам приоритета:
Когда запрос точно совпадает со словом в списке слов (с учетом регистра), вы должны вернуть это же слово.
Когда запрос совпадает со словом за исключением регистра, вы должны вернуть первое такое совпадение в списке слов.
Когда запрос совпадает со словом за исключением ошибок гласных, вы должны вернуть первое такое совпадение в списке слов.
Если запрос не имеет совпадений в списке слов, вы должны вернуть пустую строку.
Дан массив запросов, верните список слов answer, где answer[i] — правильное слово для query = queries[i].

Пример:
Input: wordlist = ["KiTe","kite","hare","Hare"], queries = ["kite","Kite","KiTe","Hare","HARE","Hear","hear","keti","keet","keto"]
Output: ["kite","KiTe","KiTe","Hare","hare","","","KiTe","","KiTe"]


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

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

2⃣Используйте хэш-таблицу для хранения слов в нижнем регистре и соответствующих слов из списка для проверки совпадений без учета регистра.

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

😎 Решение:
class Solution {
Set<String> words_perfect;
Map<String, String> words_cap;
Map<String, String> words_vow;

public String[] spellchecker(String[] wordlist, String[] queries) {
words_perfect = new HashSet();
words_cap = new HashMap();
words_vow = new HashMap();

for (String word: wordlist) {
words_perfect.add(word);

String wordlow = word.toLowerCase();
words_cap.putIfAbsent(wordlow, word);

String wordlowDV = devowel(wordlow);
words_vow.putIfAbsent(wordlowDV, word);
}

String[] ans = new String[queries.length];
int t = 0;
for (String query: queries)
ans[t++] = solve(query);
return ans;
}

public String solve(String query) {
if (words_perfect.contains(query))
return query;

String queryL = query.toLowerCase();
if (words_cap.containsKey(queryL))
return words_cap.get(queryL);

String queryLV = devowel(queryL);
if (words_vow.containsKey(queryLV))
return words_vow.get(queryLV);

return "";
}

public String devowel(String word) {
StringBuilder ans = new StringBuilder();
for (char c: word.toCharArray())
ans.append(isVowel(c) ? '*' : c);
return ans.toString();
}

public boolean isVowel(char c) {
return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u');
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1190. Reverse Substrings Between Each Pair of Parentheses
Сложность: medium

Дана строка s, состоящая из строчных букв английского алфавита и скобок.

Переверните строки в каждой паре соответствующих скобок, начиная с самой внутренней.

Ваш результат не должен содержать скобок.

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


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

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

2⃣Для каждого символа currentChar во входной строке:
Если это '(', добавьте длину строки result в openParenthesesIndices, чтобы отметить потенциальную начальную точку разворота.
Если это ')', извлеките значение из openParenthesesIndices и переверните result от извлеченного индекса для выполнения необходимого разворота.
В противном случае добавьте currentChar к result для построения строки.

3⃣Верните result как окончательную строку со всеми примененными разворотами.

😎 Решение:
class Solution {
public String reverseParentheses(String s) {
Stack<Integer> openParenthesesIndices = new Stack<>();
StringBuilder result = new StringBuilder();

for (char currentChar : s.toCharArray()) {
if (currentChar == '(') {
openParenthesesIndices.push(result.length());
} else if (currentChar == ')') {
int start = openParenthesesIndices.pop();
reverse(result, start, result.length() - 1);
} else {
result.append(currentChar);
}
}

return result.toString();
}

private void reverse(StringBuilder sb, int start, int end) {
while (start < end) {
char temp = sb.charAt(start);
sb.setCharAt(start++, sb.charAt(end));
sb.setCharAt(end--, temp);
}
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Задача: 625. Minimum Factorization
Сложность: medium

Если задано целое положительное число num, верните наименьшее целое положительное число x, умножение каждого разряда которого равно num. Если ответа нет или ответ не помещается в 32-битное знаковое целое число, возвращается 0.

Пример:
Input: num = 48
Output: 68


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

1⃣Если num равно 1, верните 1. Инициализируйте массив для хранения множителей.

2⃣Разделите num на множители от 9 до 2, пока num больше 1. Если в процессе остаются множители больше 9, верните 0.

3⃣Постройте результат, собирая найденные множители в обратном порядке. Если результат больше 32-битного целого числа, верните 0.

😎 Решение:
public class Solution {
public int smallestFactorization(int num) {
if (num == 1) return 1;

List<Integer> factors = new ArrayList<>();

for (int i = 9; i >= 2; i--) {
while (num % i == 0) {
factors.add(i);
num /= i;
}
}

if (num > 1) return 0;

long result = 0;
for (int i = factors.size() - 1; i >= 0; i--) {
result = result * 10 + factors.get(i);
if (result > Integer.MAX_VALUE) return 0;
}

return (int) result;
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM