Задача: 1022. Sum of Root To Leaf Binary Numbers
Сложность: easy
Вам дан корень двоичного дерева, в котором каждый узел имеет значение 0 или 1. Каждый путь от корня к листьям представляет собой двоичное число, начиная со старшего бита. Например, если путь 0 -> 1 -> 1 -> 0 -> 1, то в двоичном виде это может представлять 01101, что равно 13. Для всех листьев дерева рассмотрите числа, представленные путем от корня к этому листу. Верните сумму этих чисел. Тестовые примеры генерируются таким образом, чтобы ответ помещался в 32-битовое целое число.
Пример:
👨💻 Алгоритм:
1⃣ Рекурсивный обход дерева:
Используйте функцию DFS (поиск в глубину) для обхода дерева, начиная от корня. Передавайте текущее значение числа по пути как параметр.
2⃣ Анализ текущего узла:
Если узел является листом (не имеет потомков), добавьте текущее значение числа к общей сумме.
Если узел не является листом, рекурсивно вызовите функцию DFS для левого и правого дочерних узлов, обновляя текущее значение числа.
3⃣ Возврат результата:
После завершения обхода верните общую сумму чисел, представленных путями от корня к листьям.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Вам дан корень двоичного дерева, в котором каждый узел имеет значение 0 или 1. Каждый путь от корня к листьям представляет собой двоичное число, начиная со старшего бита. Например, если путь 0 -> 1 -> 1 -> 0 -> 1, то в двоичном виде это может представлять 01101, что равно 13. Для всех листьев дерева рассмотрите числа, представленные путем от корня к этому листу. Верните сумму этих чисел. Тестовые примеры генерируются таким образом, чтобы ответ помещался в 32-битовое целое число.
Пример:
Input: root = [1,0,1,0,1,0,1]
Output: 22
Используйте функцию DFS (поиск в глубину) для обхода дерева, начиная от корня. Передавайте текущее значение числа по пути как параметр.
Если узел является листом (не имеет потомков), добавьте текущее значение числа к общей сумме.
Если узел не является листом, рекурсивно вызовите функцию DFS для левого и правого дочерних узлов, обновляя текущее значение числа.
После завершения обхода верните общую сумму чисел, представленных путями от корня к листьям.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class Solution {
public int sumRootToLeaf(TreeNode root) {
return dfs(root, 0);
}
private int dfs(TreeNode node, int currentValue) {
if (node == null) return 0;
currentValue = (currentValue << 1) | node.val;
if (node.left == null && node.right == null) return currentValue;
return dfs(node.left, currentValue) + dfs(node.right, currentValue);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 315. Count of Smaller Numbers After Self
Сложность: hard
Дан целочисленный массив nums, верните целочисленный массив counts, где counts[i] - это количество элементов справа от nums[i], которые меньше nums[i].
Пример:
👨💻 Алгоритм:
1⃣ Реализуйте дерево отрезков (segment tree). Поскольку дерево инициализируется нулями, нужно реализовать только операции обновления и запроса. Установите смещение offset = 10^4.
2⃣ Итерация по каждому числу в nums в обратном порядке. Для каждого числа выполните следующие действия:
Смещайте число на num + offset.
Запросите количество элементов в дереве отрезков, которые меньше текущего числа.
Обновите счетчик текущего числа в дереве отрезков.
3⃣ Верните результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Дан целочисленный массив nums, верните целочисленный массив counts, где counts[i] - это количество элементов справа от nums[i], которые меньше nums[i].
Пример:
Input: nums = [5,2,6,1]
Output: [2,1,1,0]
Explanation:
To the right of 5 there are 2 smaller elements (2 and 1).
To the right of 2 there is only 1 smaller element (1).
To the right of 6 there is 1 smaller element (1).
To the right of 1 there is 0 smaller element.
Смещайте число на num + offset.
Запросите количество элементов в дереве отрезков, которые меньше текущего числа.
Обновите счетчик текущего числа в дереве отрезков.
class Solution {
public List<Integer> countSmaller(int[] nums) {
int offset = 10000;
int size = 2 * 10000 + 1;
int[] tree = new int[size * 2];
List<Integer> result = new ArrayList<Integer>();
for (int i = nums.length - 1; i >= 0; i--) {
int smaller_count = query(0, nums[i] + offset, tree, size);
result.add(smaller_count);
update(nums[i] + offset, 1, tree, size);
}
Collections.reverse(result);
return result;
}
private void update(int index, int value, int[] tree, int size) {
index += size;
tree[index] += value;
while (index > 1) {
index /= 2;
tree[index] = tree[index * 2] + tree[index * 2 + 1];
}
}
private int query(int left, int right, int[] tree, int size) {
int result = 0;
left += size;
right += size;
while (left < right) {
if (left % 2 == 1) {
result += tree[left];
left++;
}
left /= 2;
if (right % 2 == 1) {
right--;
result += tree[right];
}
right /= 2;
}
return result;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Задача: 616. Add Bold Tag in String
Сложность: medium
Вам дана строка s и массив строк words. Вы должны добавить закрытую пару полужирных тегов <b> и </b>, чтобы обернуть подстроки в s, которые существуют в words. Если две такие подстроки пересекаются, вы должны обернуть их вместе только одной парой закрытых полужирных тегов. Если две подстроки, обернутые полужирными тегами, идут подряд, вы должны объединить их. Верните s после добавления полужирных тегов.
Пример:
👨💻 Алгоритм:
1⃣ Найдите все позиции вхождений подстрок из words в строку s и пометьте эти позиции для выделения тегами <b> и </b>.
2⃣ Пройдитесь по помеченным позициям, чтобы определить области, которые нужно обернуть в полужирные теги, слияя пересекающиеся и смежные области.
3⃣ Постройте новую строку s, добавляя теги <b> и </b> в определенные позиции.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дана строка s и массив строк words. Вы должны добавить закрытую пару полужирных тегов <b> и </b>, чтобы обернуть подстроки в s, которые существуют в words. Если две такие подстроки пересекаются, вы должны обернуть их вместе только одной парой закрытых полужирных тегов. Если две подстроки, обернутые полужирными тегами, идут подряд, вы должны объединить их. Верните s после добавления полужирных тегов.
Пример:
Input: s = "abcxyz123", words = ["abc","123"]
Output: "<b>abc</b>xyz<b>123</b>"
public class Solution {
public String addBoldTag(String s, String[] words) {
int n = s.length();
boolean[] bold = new boolean[n];
for (String word : words) {
int start = s.indexOf(word);
while (start != -1) {
for (int i = start; i < start + word.length(); i++) {
bold[i] = true;
}
start = s.indexOf(word, start + 1);
}
}
StringBuilder result = new StringBuilder();
int i = 0;
while (i < n) {
if (bold[i]) {
result.append("<b>");
while (i < n && bold[i]) {
result.append(s.charAt(i));
i++;
}
result.append("</b>");
} else {
result.append(s.charAt(i));
i++;
}
}
return result.toString();
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1💊1
Задача: 559. Maximum Depth of N-ary Tree
Сложность: easy
Дано n-арное дерево, найдите его максимальную глубину.
Максимальная глубина - это количество узлов вдоль самого длинного пути от корневого узла до самого дальнего листового узла.
Сериализация ввода n-арного дерева представлена в порядке уровня, каждая группа дочерних узлов разделена значением null (см. примеры).
Пример:
👨💻 Алгоритм:
1⃣ Интуитивный подход заключается в решении задачи с помощью рекурсии.
2⃣ Здесь мы демонстрируем пример с использованием стратегии поиска в глубину (DFS - Depth First Search).
3⃣ Применяя DFS, проходим через все узлы дерева, вычисляя максимальную глубину.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дано n-арное дерево, найдите его максимальную глубину.
Максимальная глубина - это количество узлов вдоль самого длинного пути от корневого узла до самого дальнего листового узла.
Сериализация ввода n-арного дерева представлена в порядке уровня, каждая группа дочерних узлов разделена значением null (см. примеры).
Пример:
Input: root = [1,null,3,2,4,null,5,6]
Output: 3
class Solution {
public int maxDepth(Node root) {
if (root == null) {
return 0;
} else if (root.children.isEmpty()) {
return 1;
} else {
List<Integer> heights = new LinkedList<>();
for (Node item : root.children) {
heights.add(maxDepth(item));
}
return Collections.max(heights) + 1;
}
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Задача: 924. Minimize Malware Spread
Сложность: hard
Вам дана сеть из n узлов, представленная в виде графа с матрицей смежности n x n, где i-й узел непосредственно связан с j-м узлом, если graph[i][j] == 1. Некоторые узлы изначально заражены вредоносным ПО. Если два узла соединены напрямую и хотя бы один из них заражен вредоносным ПО, то оба узла будут заражены вредоносным ПО. Такое распространение вредоносного ПО будет продолжаться до тех пор, пока не останется ни одного узла, который можно было бы заразить таким образом. Предположим, что M(initial) - это конечное число узлов, зараженных вредоносным ПО, во всей сети после прекращения распространения вредоносного ПО. Мы удалим из initial ровно один узел. Верните тот узел, удаление которого минимизирует M(initial). Если можно удалить несколько узлов, чтобы минимизировать M(initial), верните такой узел с наименьшим индексом. Обратите внимание, что если узел был удален из начального списка зараженных узлов, он все равно может быть заражен позже из-за распространения вредоносного ПО.
Пример:
👨💻 Алгоритм:
1⃣ Определить количество зараженных узлов после распространения вредоносного ПО для исходного списка initial.
2⃣ Для каждого узла в initial удалить его и вычислить количество зараженных узлов после распространения вредоносного ПО.
3⃣ Найти узел, удаление которого минимизирует количество зараженных узлов. Если есть несколько таких узлов, выбрать узел с наименьшим индексом.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Вам дана сеть из n узлов, представленная в виде графа с матрицей смежности n x n, где i-й узел непосредственно связан с j-м узлом, если graph[i][j] == 1. Некоторые узлы изначально заражены вредоносным ПО. Если два узла соединены напрямую и хотя бы один из них заражен вредоносным ПО, то оба узла будут заражены вредоносным ПО. Такое распространение вредоносного ПО будет продолжаться до тех пор, пока не останется ни одного узла, который можно было бы заразить таким образом. Предположим, что M(initial) - это конечное число узлов, зараженных вредоносным ПО, во всей сети после прекращения распространения вредоносного ПО. Мы удалим из initial ровно один узел. Верните тот узел, удаление которого минимизирует M(initial). Если можно удалить несколько узлов, чтобы минимизировать M(initial), верните такой узел с наименьшим индексом. Обратите внимание, что если узел был удален из начального списка зараженных узлов, он все равно может быть заражен позже из-за распространения вредоносного ПО.
Пример:
Input: arr = [1,1,2,2,3,3,4,4,5,5], target = 8
Output: 20
import java.util.*;
class Solution {
public int minMalwareSpread(int[][] graph, int[] initial) {
int n = graph.length;
Set<Integer> initialSet = new HashSet<>();
for (int node : initial) {
initialSet.add(node);
}
Arrays.sort(initial);
int minInfected = Integer.MAX_VALUE;
int bestNode = initial[0];
for (int node : initial) {
Set<Integer> infected = new HashSet<>(initialSet);
infected.remove(node);
for (int i : initialSet) {
if (i != node) {
dfs(graph, i, infected);
}
}
if (infected.size() < minInfected) {
minInfected = infected.size();
bestNode = node;
}
}
return bestNode;
}
private void dfs(int[][] graph, int node, Set<Integer> infected) {
for (int neighbor = 0; neighbor < graph.length; neighbor++) {
if (graph[node][neighbor] == 1 && !infected.contains(neighbor)) {
infected.add(neighbor);
dfs(graph, neighbor, infected);
}
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 162. Find Peak Element
Сложность: medium
Пиковым элементом называется элемент, который строго больше своих соседей.
Для массива целых чисел nums с индексацией с нуля найдите пиковый элемент и верните его индекс. Если в массиве несколько пиков, верните индекс любого из пиков.
Вы можете представить, что nums[-1] = nums[n] = -∞. Другими словами, элемент всегда считается строго большим, чем сосед, находящийся за пределами массива.
Необходимо написать алгоритм, который работает за время O(log n).
Пример:
👨💻 Алгоритм:
1⃣ Начальная проверка:
Определяем средний элемент массива mid как mid = low + (high - low) / 2. Это помогает предотвратить возможное переполнение при больших значениях индексов.
2⃣ Определение направления поиска:
Сравниваем элемент nums[mid] с его правым соседом nums[mid + 1]. Если nums[mid] меньше nums[mid + 1], это указывает на наличие восходящей последовательности, и мы двигаемся вправо, устанавливая low = mid + 1. Это потому, что пик гарантированно находится в правой части.
Если nums[mid] больше nums[mid + 1], это указывает на наличие нисходящей последовательности, и пик находится либо в mid, либо слева от него, тогда устанавливаем high = mid.
3⃣ Завершение поиска:
Процесс продолжается до тех пор, пока low не станет равным high, что означает сужение поисковой области до одного элемента, который и является пиком, поскольку мы исключили все другие возможности.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Пиковым элементом называется элемент, который строго больше своих соседей.
Для массива целых чисел nums с индексацией с нуля найдите пиковый элемент и верните его индекс. Если в массиве несколько пиков, верните индекс любого из пиков.
Вы можете представить, что nums[-1] = nums[n] = -∞. Другими словами, элемент всегда считается строго большим, чем сосед, находящийся за пределами массива.
Необходимо написать алгоритм, который работает за время O(log n).
Пример:
Input: nums = [1,2,3,1]
Output: 2
Explanation: 3 is a peak element and your function should return the index number 2.
Определяем средний элемент массива mid как mid = low + (high - low) / 2. Это помогает предотвратить возможное переполнение при больших значениях индексов.
Сравниваем элемент nums[mid] с его правым соседом nums[mid + 1]. Если nums[mid] меньше nums[mid + 1], это указывает на наличие восходящей последовательности, и мы двигаемся вправо, устанавливая low = mid + 1. Это потому, что пик гарантированно находится в правой части.
Если nums[mid] больше nums[mid + 1], это указывает на наличие нисходящей последовательности, и пик находится либо в mid, либо слева от него, тогда устанавливаем high = mid.
Процесс продолжается до тех пор, пока low не станет равным high, что означает сужение поисковой области до одного элемента, который и является пиком, поскольку мы исключили все другие возможности.
public class Solution {
public int findPeakElement(int[] nums) {
return search(nums, 0, nums.length - 1);
}
public int search(int[] nums, int l, int r) {
if (l == r) return l;
int mid = (l + r) / 2;
if (nums[mid] > nums[mid + 1]) return search(nums, l, mid);
return search(nums, mid + 1, r);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Задача: 319. Bulb Switcher
Сложность: medium
Есть n лампочек, которые изначально выключены. Сначала вы включаете все лампочки, затем выключаете каждую вторую лампочку.
На третьем раунде вы переключаете каждую третью лампочку (включаете, если она выключена, или выключаете, если она включена). На i-ом раунде вы переключаете каждую i-ую лампочку. На n-ом раунде вы переключаете только последнюю лампочку.
Верните количество лампочек, которые будут включены после n раундов.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация
Лампочка остается включенной, если она переключалась нечетное количество раз. Лампочка будет переключаться на каждом делителе её номера.
2⃣ Определение состояния лампочки
Лампочка останется включенной только в том случае, если у нее нечетное количество делителей, что возможно только для квадратных чисел.
3⃣ Подсчет включенных лампочек
Количество лампочек, которые будут включены после n раундов.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Есть n лампочек, которые изначально выключены. Сначала вы включаете все лампочки, затем выключаете каждую вторую лампочку.
На третьем раунде вы переключаете каждую третью лампочку (включаете, если она выключена, или выключаете, если она включена). На i-ом раунде вы переключаете каждую i-ую лампочку. На n-ом раунде вы переключаете только последнюю лампочку.
Верните количество лампочек, которые будут включены после n раундов.
Пример:
Input: n = 3
Output: 1
Explanation: At first, the three bulbs are [off, off, off].
After the first round, the three bulbs are [on, on, on].
After the second round, the three bulbs are [on, off, on].
After the third round, the three bulbs are [on, off, off].
So you should return 1 because there is only one bulb is on.
Explanation: The two words can be "abcw", "xtfn".
Лампочка остается включенной, если она переключалась нечетное количество раз. Лампочка будет переключаться на каждом делителе её номера.
Лампочка останется включенной только в том случае, если у нее нечетное количество делителей, что возможно только для квадратных чисел.
Количество лампочек, которые будут включены после n раундов.
class Solution {
public int bulbSwitch(int n) {
return (int) Math.sqrt(n);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👍1
Задача: 819. Most Common Word
Сложность: easy
Дана строка paragraph и массив строк banned, представляющий запрещенные слова. Верните наиболее часто встречающееся слово, которое не запрещено. Гарантируется, что существует хотя бы одно слово, которое не запрещено, и что ответ является уникальным.
Слова в paragraph нечувствительны к регистру, и ответ должен быть возвращен в нижнем регистре.
Пример:
👨💻 Алгоритм:
1⃣ Заменяем всю пунктуацию пробелами и одновременно переводим каждую букву в нижний регистр. Это можно сделать и в два этапа, но здесь мы объединяем их в один этап.
2⃣ Разбиваем полученный результат на слова, используя пробелы в качестве разделителей.
3⃣ Затем итерируемся по словам, чтобы подсчитать количество появлений каждого уникального слова, исключая слова из списка запрещенных. С помощью хеш-таблицы {слово->количество} проходим по всем элементам, чтобы найти слово с наивысшей частотой.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дана строка paragraph и массив строк banned, представляющий запрещенные слова. Верните наиболее часто встречающееся слово, которое не запрещено. Гарантируется, что существует хотя бы одно слово, которое не запрещено, и что ответ является уникальным.
Слова в paragraph нечувствительны к регистру, и ответ должен быть возвращен в нижнем регистре.
Пример:
Input: paragraph = "Bob hit a ball, the hit BALL flew far after it was hit.", banned = ["hit"]
Output: "ball"
Explanation:
"hit" occurs 3 times, but it is a banned word.
"ball" occurs twice (and no other word does), so it is the most frequent non-banned word in the paragraph.
Note that words in the paragraph are not case sensitive,
that punctuation is ignored (even if adjacent to words, such as "ball,"),
and that "hit" isn't the answer even though it occurs more because it is banned.
class Solution {
public String mostCommonWord(String paragraph, List<String> banned) {
String normalizedStr = paragraph.replaceAll("[^a-zA-Z0-9 ]", " ").toLowerCase();
String[] words = normalizedStr.split("\\s+");
Map<String, Integer> wordCount = new HashMap<>();
Set<String> bannedWords = new HashSet<>(banned);
for (String word : words) {
if (!bannedWords.contains(word)) {
wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
}
}
return Collections.max(wordCount.entrySet(), Map.Entry.comparingByValue()).getKey();
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1💊1
Задача: 387. First Unique Character in a String
Сложность: easy
Дана строка s, найдите первый неповторяющийся символ в ней и верните его индекс. Если такого символа не существует, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Постройте хеш-таблицу, где ключами являются символы строки, а значениями — количество их появлений. Для этого пройдите по строке и для каждого символа увеличивайте его счетчик в хеш-таблице.
2⃣ Пройдите по строке снова и проверьте для каждого символа, является ли его количество появлений в хеш-таблице равным 1.
3⃣ Если найдется символ с количеством появлений, равным 1, верните его индекс. Если такой символ не найден, верните -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дана строка s, найдите первый неповторяющийся символ в ней и верните его индекс. Если такого символа не существует, верните -1.
Пример:
Input: s = "leetcode"
Output: 0
import java.util.Random;
public class Solution {
private int[] original;
private int[] array;
private Random rand = new Random();
public Solution(int[] nums) {
array = nums.clone();
original = nums.clone();
}
public int[] reset() {
array = original.clone();
return original;
}
public int[] shuffle() {
for (int i = 0; i < array.length; i++) {
int randIndex = rand.nextInt(array.length - i) + i;
int temp = array[i];
array[i] = array[randIndex];
array[randIndex] = temp;
}
return array;
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊5
Задача: 54. Spiral Matrix
Сложность: medium
Для матрицы размером m на n верните все элементы матрицы в спиральном порядке.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируемая граница: up, down, left, right, а также список resultдля сохранения результата.
2⃣ Пока размер результата уменьшает общее количество элементов: продвигается по верхней строке влево вправо, вправо столбцу вверху вниз, нижней строке справа налево (если строки не поворачиваются), левый столбец увеличивается вверх (если столбцы не поворачиваются).
3⃣ После каждого прохождения обновляем границу: смещаемся вверх, вниз, влево и вправо вправо.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Для матрицы размером m на n верните все элементы матрицы в спиральном порядке.
Пример:
Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output: [1,2,3,6,9,8,7,4,5]
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new ArrayList<>();
int rows = matrix.length;
int columns = matrix[0].length;
int up = 0;
int left = 0;
int right = columns - 1;
int down = rows - 1;
while (result.size() < rows * columns) {
for (int col = left; col <= right; col++) {
result.add(matrix[up][col]);
}
for (int row = up + 1; row <= down; row++) {
result.add(matrix[row][right]);
}
if (up != down) {
for (int col = right - 1; col >= left; col--) {
result.add(matrix[down][col]);
}
}
if (left != right) {
for (int row = down - 1; row > up; row--) {
result.add(matrix[row][left]);
}
}
left++;
right--;
up++;
down--;
}
return result;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 443. String Compression
Сложность: medium
Дан массив символов chars, сжать его, используя следующий алгоритм:
Начните с пустой строки s. Для каждой группы последовательных повторяющихся символов в chars:
Если длина группы равна 1, добавьте символ к строке s.
В противном случае добавьте символ, а за ним длину группы.
Сжатая строка s не должна возвращаться отдельно, а вместо этого должна быть сохранена в входном массиве символов chars. Обратите внимание, что длины групп, которые равны 10 или более, будут разделены на несколько символов в chars.
После того как вы закончите модификацию входного массива, верните новую длину массива.
Вы должны написать алгоритм, который использует только постоянное дополнительное пространство.
Пример:
👨💻 Алгоритм:
1⃣ Объявите переменные i – первый индекс текущей группы, и res – длина ответа (сжатой строки). Инициализируйте i = 0, res = 0.
2⃣ Пока i меньше длины chars: Найдите длину текущей группы последовательных повторяющихся символов groupLength. Добавьте chars[i] к ответу (chars[res++] = chars[i]). Если groupLength > 1, добавьте строковое представление groupLength к ответу и увеличьте res соответственно. Увеличьте i на groupLength и перейдите к следующей группе.
3⃣ Верните res.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив символов chars, сжать его, используя следующий алгоритм:
Начните с пустой строки s. Для каждой группы последовательных повторяющихся символов в chars:
Если длина группы равна 1, добавьте символ к строке s.
В противном случае добавьте символ, а за ним длину группы.
Сжатая строка s не должна возвращаться отдельно, а вместо этого должна быть сохранена в входном массиве символов chars. Обратите внимание, что длины групп, которые равны 10 или более, будут разделены на несколько символов в chars.
После того как вы закончите модификацию входного массива, верните новую длину массива.
Вы должны написать алгоритм, который использует только постоянное дополнительное пространство.
Пример:
Input: chars = ["a","a","b","b","c","c","c"]
Output: Return 6, and the first 6 characters of the input array should be: ["a","2","b","2","c","3"]
Explanation: The groups are "aa", "bb", and "ccc". This compresses to "a2b2c3".
class Solution {
public int compress(char[] chars) {
int i = 0;
int res = 0;
while (i < chars.length) {
int groupLength = 1;
while (i + groupLength < chars.length && chars[i + groupLength] == chars[i]) {
groupLength++;
}
chars[res++] = chars[i];
if (groupLength > 1) {
String strRepr = Integer.toString(groupLength);
for (char ch : strRepr.toCharArray()) {
chars[res++] = ch;
}
}
i += groupLength;
}
return res;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 414. Third Maximum Number
Сложность: easy
Если задан целочисленный массив nums, верните третье максимальное число в этом массиве. Если третьего максимального числа не существует, верните максимальное число.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте три переменные для хранения первого, второго и третьего максимальных чисел, используя значения None или аналогичные значения.
2⃣ Пройдитесь по массиву, обновляя переменные первого, второго и третьего максимальных чисел, избегая дубликатов.
3⃣ Если третье максимальное число существует, верните его. В противном случае, верните первое максимальное число.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Если задан целочисленный массив nums, верните третье максимальное число в этом массиве. Если третьего максимального числа не существует, верните максимальное число.
Пример:
Input: nums = [3,2,1]
Output: 1
import java.util.HashSet;
import java.util.Set;
public class Solution {
public int thirdMax(int[] nums) {
Integer first = null;
Integer second = null;
Integer third = null;
for (Integer num : nums) {
if (num.equals(first) || num.equals(second) || num.equals(third)) {
continue;
}
if (first == null || num > first) {
third = second;
second = first;
first = num;
} else if (second == null || num > second) {
third = second;
second = num;
} else if (third == null || num > third) {
third = num;
}
}
return third != null ? third : first;
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Задача: 1263. Minimum Moves to Move a Box to Their Target Location
Сложность: hard
Кладовщик - это игра, в которой игрок перемещает коробки по складу, пытаясь доставить их в целевые места. Игра представлена сеткой символов m x n, где каждый элемент - это стена, пол или коробка. Ваша задача - переместить коробку "B" в целевую позицию "T" по следующим правилам: символ "S" представляет игрока. Игрок может перемещаться вверх, вниз, влево, вправо по сетке, если это пол (пустая клетка). Символ '.' обозначает пол, что означает свободную клетку для ходьбы. Символ '#' обозначает стену, что означает препятствие (туда невозможно пройти). В сетке есть только одна коробка 'B' и одна целевая клетка 'T'. Коробку можно переместить на соседнюю свободную клетку, стоя рядом с коробкой, а затем двигаясь в направлении коробки. Это толчок. Игрок не может пройти через коробку. Верните минимальное количество толчков, чтобы переместить коробку к цели. Если нет возможности добраться до цели, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Выполните поиск в ширину (BFS) для всех возможных позиций игрока и коробки, отслеживая количество толчков.
2⃣ Используйте очередь для хранения состояний игрока и коробки, а также текущего количества толчков.
3⃣ Для каждого состояния проверяйте все возможные движения игрока и перемещения коробки, обновляйте очередь и отмечайте посещенные состояния.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Кладовщик - это игра, в которой игрок перемещает коробки по складу, пытаясь доставить их в целевые места. Игра представлена сеткой символов m x n, где каждый элемент - это стена, пол или коробка. Ваша задача - переместить коробку "B" в целевую позицию "T" по следующим правилам: символ "S" представляет игрока. Игрок может перемещаться вверх, вниз, влево, вправо по сетке, если это пол (пустая клетка). Символ '.' обозначает пол, что означает свободную клетку для ходьбы. Символ '#' обозначает стену, что означает препятствие (туда невозможно пройти). В сетке есть только одна коробка 'B' и одна целевая клетка 'T'. Коробку можно переместить на соседнюю свободную клетку, стоя рядом с коробкой, а затем двигаясь в направлении коробки. Это толчок. Игрок не может пройти через коробку. Верните минимальное количество толчков, чтобы переместить коробку к цели. Если нет возможности добраться до цели, верните -1.
Пример:
Input: grid = [["#","#","#","#","#","#"],
["#","T","#","#","#","#"],
["#",".",".","B",".","#"],
["#",".","#","#",".","#"],
["#",".",".",".","S","#"],
["#","#","#","#","#","#"]]
Output: 3
import java.util.*;
public class Solution {
public int minPushBox(char[][] grid) {
int m = grid.length, n = grid[0].length;
int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
Queue<int[]> queue = new LinkedList<>();
Set<String> visited = new HashSet<>();
int[] player = new int[2], box = new int[2], target = new int[2];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 'S') {
player = new int[]{i, j};
} else if (grid[i][j] == 'B') {
box = new int[]{i, j};
} else if (grid[i][j] == 'T') {
target = new int[]{i, j};
}
}
}
queue.offer(new int[]{player[0], player[1], box[0], box[1], 0});
visited.add(player[0] + "," + player[1] + "," + box[0] + "," + box[1]);
while (!queue.isEmpty()) {
int[] state = queue.poll();
int px = state[0], py = state[1], bx = state[2], by = state[3], pushes = state[4];
if (bx == target[0] && by == target[1]) {
return pushes;
}
for (int[] dir : directions) {
int npx = px + dir[0], npy = py + dir[1];
if (isValid(npx, npy, m, n, grid)) {
if (npx == bx && npy == by) {
int nbx = bx + dir[0], nby = by + dir[1];
if (isValid(nbx, nby, m, n, grid) && visited.add(npx + "," + npy + "," + nbx + "," + nby)) {
queue.offer(new int[]{npx, npy, nbx, nby, pushes + 1});
}
} else if (visited.add(npx + "," + npy + "," + bx + "," + by)) {
queue.offer(new int[]{npx, npy, bx, by, pushes});
}
}
}
}
return -1;
}
private boolean isValid(int x, int y, int m, int n, char[][] grid) {
return x >= 0 && x < m && y >= 0 && y < n && grid[x][y] != '#';
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊2
Задача: 660. Remove 9
Сложность: hard
Начните с целого числа 1, уберите любое число, которое содержит 9, такое как 9, 19, 29...
Теперь у вас будет новая последовательность целых чисел [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, ...].
Дано целое число n, верните n-е (начиная с 1) целое число в новой последовательности.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация:
Начните с числа 1 и создайте переменную для отслеживания количества найденных чисел, не содержащих цифру 9.
2⃣ Итерация и проверка:
Последовательно увеличивайте число и проверяйте, содержит ли оно цифру 9.
Если не содержит, увеличьте счетчик.
3⃣ Поиск n-го числа:
Продолжайте процесс до тех пор, пока не найдете n-е число, не содержащее цифру 9.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Начните с целого числа 1, уберите любое число, которое содержит 9, такое как 9, 19, 29...
Теперь у вас будет новая последовательность целых чисел [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, ...].
Дано целое число n, верните n-е (начиная с 1) целое число в новой последовательности.
Пример:
Input: n = 9
Output: 10
Начните с числа 1 и создайте переменную для отслеживания количества найденных чисел, не содержащих цифру 9.
Последовательно увеличивайте число и проверяйте, содержит ли оно цифру 9.
Если не содержит, увеличьте счетчик.
Продолжайте процесс до тех пор, пока не найдете n-е число, не содержащее цифру 9.
public class Solution {
public int newInteger(int n) {
int count = 0;
int num = 0;
while (count < n) {
num++;
if (!Integer.toString(num).contains("9")) {
count++;
}
}
return num;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔2💊1
Задача: 68. Text Justification
Сложность: hard
Дан массив строк wordsи чисел maxWidth. Нужно было отформатировать текст так, чтобы в строке были ровное число maxWidthсимволов, и она была выровнена по ширине.
Слова выводятся жадно, пробелы добавляются так, чтобы строки были выровнены, при этом слева добавляется больше пробелов. Последняя строка проводится по левому краю.
Пример:
👨💻 Алгоритм:
1⃣ Создайте два вспомогательных метода getWords и createLine, описанные выше.
2⃣ Инициализируйте список ответов ans и целочисленную переменную i для итерации по входным данным. Используйте цикл while для перебора входных данных. Каждая итерация в цикле while будет обрабатывать одну строку в ответе.
3⃣ Пока i < words.length, выполните следующие шаги:
Получите слова, которые должны быть в текущей строке, как currentLine = getWords(i).
Увеличьте i на currentLine.length.
Создайте строку, вызвав createLine(line, i), и добавьте её в ans.
Верните ans.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Дан массив строк wordsи чисел maxWidth. Нужно было отформатировать текст так, чтобы в строке были ровное число maxWidthсимволов, и она была выровнена по ширине.
Слова выводятся жадно, пробелы добавляются так, чтобы строки были выровнены, при этом слева добавляется больше пробелов. Последняя строка проводится по левому краю.
Пример:
Input: words = ["This", "is", "an", "example", "of", "text", "justification."], maxWidth = 16
Output:
[
"This is an",
"example of text",
"justification. "
]
Получите слова, которые должны быть в текущей строке, как currentLine = getWords(i).
Увеличьте i на currentLine.length.
Создайте строку, вызвав createLine(line, i), и добавьте её в ans.
Верните ans.
class Solution {
public List<String> fullJustify(String[] words, int maxWidth) {
List<String> ans = new ArrayList<>();
int i = 0;
while (i < words.length) {
List<String> currentLine = getWords(i, words, maxWidth);
i += currentLine.size();
ans.add(createLine(currentLine, i, words, maxWidth));
}
return ans;
}
private List<String> getWords(int i, String[] words, int maxWidth) {
List<String> currentLine = new ArrayList<>();
int currLength = 0;
while (i < words.length && currLength + words[i].length() <= maxWidth) {
currentLine.add(words[i]);
currLength += words[i].length() + 1;
i++;
}
return currentLine;
}
private String createLine(
List<String> line,
int i,
String[] words,
int maxWidth
) {
int baseLength = -1;
for (String word : line) {
baseLength += word.length() + 1;
}
int extraSpaces = maxWidth - baseLength;
if (line.size() == 1 || i == words.length) {
return String.join(" ", line) + " ".repeat(extraSpaces);
}
int wordCount = line.size() - 1;
int spacesPerWord = extraSpaces / wordCount;
int needsExtraSpace = extraSpaces % wordCount;
for (int j = 0; j < needsExtraSpace; j++) {
line.set(j, line.get(j) + " ");
}
for (int j = 0; j < wordCount; j++) {
line.set(j, line.get(j) + " ".repeat(spacesPerWord));
}
return String.join(" ", line);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 505. The Maze II
Сложность: medium
В лабиринте есть мячик с пустыми пространствами (обозначенными как 0) и стенами (обозначенными как 1). Мячик может перемещаться через пустые пространства, катясь вверх, вниз, влево или вправо, но он не остановится, пока не столкнется со стеной. Когда мячик останавливается, он может выбрать следующее направление.
Дан лабиринт размером m x n, начальная позиция мяча и пункт назначения, где start = [startrow, startcol] и destination = [destinationrow, destinationcol]. Верните кратчайшее расстояние, на которое мячик должен остановиться в пункте назначения. Если мячик не может остановиться в пункте назначения, верните -1.
Расстояние — это количество пройденных пустых пространств мячиком от начальной позиции (исключительно) до пункта назначения (включительно).
Предположим, что границы лабиринта — это стены. В примере ниже они не указаны.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация
Создайте массив distance для хранения минимальных расстояний до каждой позиции, инициализируйте его большими значениями. Установите начальную позицию start на нулевое расстояние и добавьте её в очередь.
2⃣ Обход лабиринта
Используйте очередь для выполнения обхода в ширину (BFS). Для каждой позиции извлеките из очереди текущую позицию и исследуйте все возможные направления до столкновения со стеной, отслеживая количество шагов.
3⃣ Обновление расстояний
Если достигнутая новая позиция может быть достигнута меньшим числом шагов, обновите distance и добавьте эту позицию в очередь. После завершения обхода верните минимальное расстояние до пункта назначения или -1, если его нельзя достичь.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
В лабиринте есть мячик с пустыми пространствами (обозначенными как 0) и стенами (обозначенными как 1). Мячик может перемещаться через пустые пространства, катясь вверх, вниз, влево или вправо, но он не остановится, пока не столкнется со стеной. Когда мячик останавливается, он может выбрать следующее направление.
Дан лабиринт размером m x n, начальная позиция мяча и пункт назначения, где start = [startrow, startcol] и destination = [destinationrow, destinationcol]. Верните кратчайшее расстояние, на которое мячик должен остановиться в пункте назначения. Если мячик не может остановиться в пункте назначения, верните -1.
Расстояние — это количество пройденных пустых пространств мячиком от начальной позиции (исключительно) до пункта назначения (включительно).
Предположим, что границы лабиринта — это стены. В примере ниже они не указаны.
Пример:
Input: maze = [[0,0,1,0,0],[0,0,0,0,0],[0,0,0,1,0],[1,1,0,1,1],[0,0,0,0,0]], start = [0,4], destination = [4,4]
Output: 12
Explanation: One possible way is : left -> down -> left -> down -> right -> down -> right.
The length of the path is 1 + 1 + 3 + 1 + 2 + 2 + 2 = 12.
Создайте массив distance для хранения минимальных расстояний до каждой позиции, инициализируйте его большими значениями. Установите начальную позицию start на нулевое расстояние и добавьте её в очередь.
Используйте очередь для выполнения обхода в ширину (BFS). Для каждой позиции извлеките из очереди текущую позицию и исследуйте все возможные направления до столкновения со стеной, отслеживая количество шагов.
Если достигнутая новая позиция может быть достигнута меньшим числом шагов, обновите distance и добавьте эту позицию в очередь. После завершения обхода верните минимальное расстояние до пункта назначения или -1, если его нельзя достичь.
public class Solution {
public int shortestDistance(int[][] maze, int[] start, int[] dest) {
int[][] distance = new int[maze.length][maze[0].length];
for (int[] row: distance)
Arrays.fill(row, Integer.MAX_VALUE);
distance[start[0]][start[1]] = 0;
int[][] dirs={{0, 1} ,{0, -1}, {-1, 0}, {1, 0}};
Queue < int[] > queue = new LinkedList < > ();
queue.add(start);
while (!queue.isEmpty()) {
int[] s = queue.remove();
for (int[] dir: dirs) {
int x = s[0] + dir[0];
int y = s[1] + dir[1];
int count = 0;
while (x >= 0 && y >= 0 && x < maze.length && y < maze[0].length && maze[x][y] == 0) {
x += dir[0];
y += dir[1];
count++;
}
if (distance[s[0]][s[1]] + count < distance[x - dir[0]][y - dir[1]]) {
distance[x - dir[0]][y - dir[1]] = distance[s[0]][s[1]] + count;
queue.add(new int[] {x - dir[0], y - dir[1]});
}
}
}
return distance[dest[0]][dest[1]] == Integer.MAX_VALUE ? -1 : distance[dest[0]][dest[1]];
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
Задача: 1473. Paint House III
Сложность: hard
Есть ряд из m домов в маленьком городе, каждый дом должен быть покрашен одним из n цветов (обозначены от 1 до n), некоторые дома, которые были покрашены прошлым летом, не должны быть перекрашены.
Соседство — это максимальная группа непрерывных домов, которые покрашены в один и тот же цвет.
Например: дома = [1,2,2,3,3,2,1,1] содержат 5 соседств [{1}, {2,2}, {3,3}, {2}, {1,1}].
Дан массив домов, матрица m x n стоимости и целое число target, где:
houses[i]: цвет дома i, и 0, если дом ещё не покрашен.
cost[i][j]: стоимость покраски дома i в цвет j + 1.
Верните минимальную стоимость покраски всех оставшихся домов таким образом, чтобы было ровно target соседств. Если это невозможно, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и базовые случаи:
Создайте класс Solution и массив memo для мемоизации результатов. Установите MAX_COST как максимально возможную стоимость плюс 1.
Создайте метод findMinCost, который проверяет базовые случаи:
- если все дома пройдены, возвращайте 0, если количество соседств равно target, иначе возвращайте MAX_COST.
- если количество соседств больше target, возвращайте MAX_COST.
Если результат уже вычислен, возвращайте его из memo.
2⃣ Рекурсивное вычисление минимальной стоимости:
Если дом уже покрашен, обновите количество соседств и вызовите рекурсивный метод для следующего дома.
Если дом не покрашен, попробуйте покрасить его в каждый возможный цвет, обновите количество соседств и вызовите рекурсивный метод для следующего дома. Храните минимальную стоимость.
3⃣ Метод minCost:
Запустите метод findMinCost с начальными параметрами и верните результат. Если результат равен MAX_COST, верните -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Есть ряд из m домов в маленьком городе, каждый дом должен быть покрашен одним из n цветов (обозначены от 1 до n), некоторые дома, которые были покрашены прошлым летом, не должны быть перекрашены.
Соседство — это максимальная группа непрерывных домов, которые покрашены в один и тот же цвет.
Например: дома = [1,2,2,3,3,2,1,1] содержат 5 соседств [{1}, {2,2}, {3,3}, {2}, {1,1}].
Дан массив домов, матрица m x n стоимости и целое число target, где:
houses[i]: цвет дома i, и 0, если дом ещё не покрашен.
cost[i][j]: стоимость покраски дома i в цвет j + 1.
Верните минимальную стоимость покраски всех оставшихся домов таким образом, чтобы было ровно target соседств. Если это невозможно, верните -1.
Пример:
Input: houses = [0,0,0,0,0], cost = [[1,10],[10,1],[10,1],[1,10],[5,1]], m = 5, n = 2, target = 3
Output: 9
Explanation: Paint houses of this way [1,2,2,1,1]
This array contains target = 3 neighborhoods, [{1}, {2,2}, {1,1}].
Cost of paint all houses (1 + 1 + 1 + 1 + 5) = 9.
Создайте класс Solution и массив memo для мемоизации результатов. Установите MAX_COST как максимально возможную стоимость плюс 1.
Создайте метод findMinCost, который проверяет базовые случаи:
- если все дома пройдены, возвращайте 0, если количество соседств равно target, иначе возвращайте MAX_COST.
- если количество соседств больше target, возвращайте MAX_COST.
Если результат уже вычислен, возвращайте его из memo.
Если дом уже покрашен, обновите количество соседств и вызовите рекурсивный метод для следующего дома.
Если дом не покрашен, попробуйте покрасить его в каждый возможный цвет, обновите количество соседств и вызовите рекурсивный метод для следующего дома. Храните минимальную стоимость.
Запустите метод findMinCost с начальными параметрами и верните результат. Если результат равен MAX_COST, верните -1.
class Solution {
Integer[][][] memo = new Integer[100][100][21];
final int MAX_COST = 1000001;
int findMinCost(int[] houses, int[][] cost, int targetCount, int currIndex,
int neighborhoodCount, int prevHouseColor) {
if (currIndex == houses.length) {
return neighborhoodCount == targetCount ? 0 : MAX_COST;
}
if (neighborhoodCount > targetCount) {
return MAX_COST;
}
if (memo[currIndex][neighborhoodCount][prevHouseColor] != null) {
return memo[currIndex][neighborhoodCount][prevHouseColor];
}
int minCost = MAX_COST;
if (houses[currIndex] != 0) {
int newNeighborhoodCount = neighborhoodCount + (houses[currIndex] != prevHouseColor ? 1 : 0);
minCost =
findMinCost(houses, cost, targetCount, currIndex + 1, newNeighborhoodCount, houses[currIndex]);
} else {
int totalColors = cost[0].length;
for (int color = 1; color <= totalColors; color++) {
int newNeighborhoodCount = neighborhoodCount + (color != prevHouseColor ? 1 : 0);
int currCost = cost[currIndex][color - 1]
+ findMinCost(houses, cost, targetCount, currIndex + 1, newNeighborhoodCount, color);
minCost = Math.min(minCost, currCost);
}
}
return memo[currIndex][neighborhoodCount][prevHouseColor] = minCost;
}
public int minCost(int[] houses, int[][] cost, int m, int n, int target) {
int answer = findMinCost(houses, cost, target, 0, 0, 0);
return answer == MAX_COST ? -1 : answer;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1💊1
Задача: 993. Cousins in Binary Tree
Сложность: easy
Дан корень бинарного дерева с уникальными значениями и значения двух различных узлов дерева x и y. Верните true, если узлы, соответствующие значениям x и y в дереве, являются кузенами, иначе верните false.
Два узла бинарного дерева являются кузенами, если они находятся на одной глубине и имеют разных родителей.
Обратите внимание, что в бинарном дереве корневой узел находится на глубине 0, а дети каждого узла глубины k находятся на глубине k + 1.
Пример:
👨💻 Алгоритм:
1⃣ Поиск глубины и родителя для каждого узла:
Используйте поиск в глубину (DFS) для обхода дерева.
Для каждого узла сохраняйте его глубину и родителя, если значение узла равно x или y.
2⃣ Проверка условий на кузенов:
Узлы являются кузенами, если они находятся на одной глубине, но имеют разных родителей.
3⃣ Возврат результата:
Если узлы удовлетворяют условиям на кузенов, верните true, иначе верните false.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан корень бинарного дерева с уникальными значениями и значения двух различных узлов дерева x и y. Верните true, если узлы, соответствующие значениям x и y в дереве, являются кузенами, иначе верните false.
Два узла бинарного дерева являются кузенами, если они находятся на одной глубине и имеют разных родителей.
Обратите внимание, что в бинарном дереве корневой узел находится на глубине 0, а дети каждого узла глубины k находятся на глубине k + 1.
Пример:
Input: root = [1,2,3,4], x = 4, y = 3
Output: false
Используйте поиск в глубину (DFS) для обхода дерева.
Для каждого узла сохраняйте его глубину и родителя, если значение узла равно x или y.
Узлы являются кузенами, если они находятся на одной глубине, но имеют разных родителей.
Если узлы удовлетворяют условиям на кузенов, верните true, иначе верните false.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public class Solution {
private TreeNode parentX = null;
private TreeNode parentY = null;
private int depthX = -1;
private int depthY = -1;
public boolean isCousins(TreeNode root, int x, int y) {
dfs(root, null, 0, x, y);
return depthX == depthY && parentX != parentY;
}
private void dfs(TreeNode node, TreeNode parent, int depth, int x, int y) {
if (node == null) {
return;
}
if (node.val == x) {
parentX = parent;
depthX = depth;
} else if (node.val == y) {
parentY = parent;
depthY = depth;
} else {
dfs(node.left, node, depth + 1, x, y);
dfs(node.right, node, depth + 1, x, y);
}
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Задача: 1004. Max Consecutive Ones III
Сложность: medium
Если задан двоичный массив nums и целое число k, верните максимальное количество последовательных 1 в массиве, если можно перевернуть не более k 0.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация оконного подхода:
Используйте два указателя для создания скользящего окна. Инициализируйте левый указатель в начале массива, правый указатель будет двигаться по массиву. Создайте переменную для подсчета количества нулей в текущем окне.
2⃣ Перемещение правого указателя и обновление окна:
Перемещайте правый указатель по массиву, обновляя количество нулей в текущем окне. Если количество нулей превышает k, сдвиньте левый указатель вправо до тех пор, пока количество нулей снова не станет допустимым (меньше или равно k).
3⃣ Подсчет максимального количества последовательных единиц:
На каждом шаге обновляйте максимальное количество последовательных единиц, сравнивая текущую длину окна (разница между правым и левым указателями) с текущим максимумом.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Если задан двоичный массив nums и целое число k, верните максимальное количество последовательных 1 в массиве, если можно перевернуть не более k 0.
Пример:
Input: nums = [1,1,1,0,0,0,1,1,1,1,0], k = 2
Output: 6
Используйте два указателя для создания скользящего окна. Инициализируйте левый указатель в начале массива, правый указатель будет двигаться по массиву. Создайте переменную для подсчета количества нулей в текущем окне.
Перемещайте правый указатель по массиву, обновляя количество нулей в текущем окне. Если количество нулей превышает k, сдвиньте левый указатель вправо до тех пор, пока количество нулей снова не станет допустимым (меньше или равно k).
На каждом шаге обновляйте максимальное количество последовательных единиц, сравнивая текущую длину окна (разница между правым и левым указателями) с текущим максимумом.
public class Solution {
public int longestOnes(int[] nums, int k) {
int left = 0, maxOnes = 0, zeroCount = 0;
for (int right = 0; right < nums.length; right++) {
if (nums[right] == 0) {
zeroCount++;
}
while (zeroCount > k) {
if (nums[left] == 0) {
zeroCount--;
}
left++;
}
maxOnes = Math.max(maxOnes, right - left + 1);
}
return maxOnes;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Задача: 1474. Delete N Nodes After M Nodes of a Linked List
Сложность: easy
Вам дано начало связанного списка и два целых числа m и n.
Пройдите по связанному списку и удалите некоторые узлы следующим образом:
Начните с головы как текущего узла.
Сохраните первые m узлов, начиная с текущего узла.
Удалите следующие n узлов.
Продолжайте повторять шаги 2 и 3, пока не достигнете конца списка.
Верните голову изменённого списка после удаления указанных узлов.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация указателей:
Инициализируйте currentNode на голову связанного списка. Этот указатель будет использоваться для линейного прохода по каждому узлу списка.
Инициализируйте lastMNode на голову связанного списка.
2⃣ Итерация по списку:
Итеративно удаляйте n узлов после m узлов, продолжая до конца списка.
Проходите m узлов, обновляя lastMNode на текущий узел. После m итераций lastMNode указывает на m-й узел.
Продолжайте итерацию по n узлам.
3⃣ Удаление узлов:
Чтобы удалить n узлов, измените указатель next у lastMNode, чтобы он указывал на currentNode после пропуска n узлов.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Вам дано начало связанного списка и два целых числа m и n.
Пройдите по связанному списку и удалите некоторые узлы следующим образом:
Начните с головы как текущего узла.
Сохраните первые m узлов, начиная с текущего узла.
Удалите следующие n узлов.
Продолжайте повторять шаги 2 и 3, пока не достигнете конца списка.
Верните голову изменённого списка после удаления указанных узлов.
Пример:
Input: head = [1,2,3,4,5,6,7,8,9,10,11,12,13], m = 2, n = 3
Output: [1,2,6,7,11,12]
Explanation: Keep the first (m = 2) nodes starting from the head of the linked List (1 ->2) show in black nodes.
Delete the next (n = 3) nodes (3 -> 4 -> 5) show in read nodes.
Continue with the same procedure until reaching the tail of the Linked List.
Head of the linked list after removing nodes is returned.
Инициализируйте currentNode на голову связанного списка. Этот указатель будет использоваться для линейного прохода по каждому узлу списка.
Инициализируйте lastMNode на голову связанного списка.
Итеративно удаляйте n узлов после m узлов, продолжая до конца списка.
Проходите m узлов, обновляя lastMNode на текущий узел. После m итераций lastMNode указывает на m-й узел.
Продолжайте итерацию по n узлам.
Чтобы удалить n узлов, измените указатель next у lastMNode, чтобы он указывал на currentNode после пропуска n узлов.
class Solution {
public ListNode deleteNodes(ListNode head, int m, int n) {
ListNode currentNode = head;
ListNode lastMNode = head;
while (currentNode != null) {
int mCount = m, nCount = n;
while (currentNode != null && mCount != 0) {
lastMNode = currentNode;
currentNode = currentNode.next;
mCount--;
}
while (currentNode != null && nCount != 0) {
currentNode = currentNode.next;
nCount--;
}
lastMNode.next = currentNode;
}
return head;
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1