Java | LeetCode
Open in Telegram
Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @easyoffer_adv
Show more6 520
Subscribers
-324 hours
-207 days
-4730 days
Posts Archive
6 520
Задача: 57. Insert Interval
Сложность: medium
Вам дан массив непересекающихся интервалов
intervals, где intervals[i] = [starti, endi] представляет начало и конец i-го интервала, и массив intervals отсортирован в порядке возрастания по starti. Вам также дан интервал newInterval = [start, end], представляющий начало и конец другого интервала.
Вставьте newInterval в массив intervals так, чтобы intervals оставался отсортированным в порядке возрастания по starti и в intervals не было бы перекрывающихся интервалов (при необходимости объедините перекрывающиеся интервалы).
Верните массив intervals после вставки.
Обратите внимание, что не обязательно модифицировать массив intervals на месте. Вы можете создать новый массив и вернуть его.
Пример:
Input: intervals = [[1,3],[6,9]], newInterval = [2,5] Output: [[1,5],[6,9]]👨💻 Алгоритм: 1⃣Инициализация переменных: Инициализируются переменные n и i для хранения размера массива интервалов и текущего индекса соответственно, а также пустой массив res для хранения результата. 2⃣Обработка случаев без перекрытия и с перекрытием: В случае отсутствия перекрытия до вставки, проходим через массив интервалов до тех пор, пока конечная точка текущего интервала меньше начальной точки нового интервала. Добавляем текущий интервал в массив res и переходим к следующему. В случае перекрытия, продолжаем обход, пока начальная точка нового интервала меньше или равна конечной точке текущего интервала. Обновляем начальные и конечные точки нового интервала, объединяя перекрывающиеся интервалы в один. 3⃣Обработка интервалов после вставки: Проходим через оставшиеся интервалы после индекса i и добавляем их в массив res. Это включает интервалы, которые следуют после нового интервала и не перекрываются с ним. Возвращаем массив res, содержащий все интервалы с корректно вставленным новым интервалом. 😎 Решение:
class Solution {
public int[][] insert(int[][] intervals, int[] newInterval) {
int n = intervals.length, i = 0;
List<int[]> res = new ArrayList<>();
while (i < n && intervals[i][1] < newInterval[0]) {
res.add(intervals[i]);
i++;
}
while (i < n && newInterval[1] >= intervals[i][0]) {
newInterval[0] = Math.min(newInterval[0], intervals[i][0]);
newInterval[1] = Math.max(newInterval[1], intervals[i][1]);
i++;
}
res.add(newInterval);
while (i < n) {
res.add(intervals[i]);
i++;
}
return res.toArray(new int[res.size()][]);
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Задача: 406. Queue Reconstruction by Height
Сложность: medium
Вам дан массив людей, people, которые являются атрибутами некоторых людей в очереди (не обязательно по порядку). Каждый people[i] = [hi, ki] представляет собой человека ростом hi, перед которым стоят ровно ki других людей, чей рост больше или равен hi. Реконструируйте и верните очередь, представленную входным массивом people. Возвращаемая очередь должна быть отформатирована как массив queue, где queue[j] = [hj, kj] - это атрибуты j-го человека в очереди (queue[0] - человек, находящийся в начале очереди).
Пример:
Input: people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]] Output: [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]👨💻 Алгоритм: 1⃣Отсортируйте массив people по убыванию роста hi. Если два человека имеют одинаковый рост, отсортируйте их по возрастанию значения ki. 2⃣Создайте пустой список для результата. Вставляйте каждого человека из отсортированного массива в список на позицию, соответствующую значению ki. 3⃣Верните список результата. 😎 Решение:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
public int[][] reconstructQueue(int[][] people) {
Arrays.sort(people, (a, b) -> a[0] == b[0] ? a[1] - b[1] : b[0] - a[0]);
List<int[]> result = new ArrayList<>();
for (int[] person : people) {
result.add(person[1], person);
}
return result.toArray(new int[result.size()][]);
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
+4
3 причины открыть ИИС в Финаме уже сегодня
Откройте индивидуальный инвестиционный счет (ИИС) в Финаме и получите расширенные возможности для формирования личного капитала.
Вы получаете сразу 3 преимущества:
✅ до 22% налогового вычета на внесённые средства
✅ дополнительную премию до 102 000 руб. за инвестиции от Финама
✅ 0% комиссия за покупку ценных бумаг на Московской бирже
Счет открывается онлайн за несколько минут. Управлять инвестициями можно самостоятельно через личный кабинет или с помощью готовых продуктов в мобильном приложении FinamTrade.
👍 Используйте все преимущества ИИС — оставьте заявку на открытие счета и начните уверенное движение к финансовым целям!
Подробнее
Финансовые услуги оказывает: АО «Инвестиционная компания «ФИНАМ».
#реклама
broker.finam.ru
О рекламодателе
6 520
Задача: 439. Ternary Expression Parser
Сложность: medium
Дана строка expression, представляющая произвольно вложенные тернарные выражения, вычислите это выражение и верните его результат.
Можно всегда считать, что данное выражение является корректным и содержит только цифры, '?', ':', 'T' и 'F', где 'T' означает истину, а 'F' - ложь. Все числа в выражении являются однозначными числами (т.е. в диапазоне от 0 до 9).
Условные выражения группируются справа налево (как обычно в большинстве языков), и результат выражения всегда будет либо цифрой, либо 'T', либо 'F'.
Пример:
Input: expression = "T?2:3" Output: "2" Explanation: If true, then result is 2; otherwise result is 3.👨💻 Алгоритм: 1⃣Определите вспомогательную функцию isValidAtomic(s), которая принимает строку s и возвращает True, если s является допустимым атомарным выражением. В противном случае функция возвращает False. Функция будет вызываться только с пятисимвольными строками. Если все следующие условия выполнены, функция возвращает True, иначе - False: s[0] является T или F. s[1] является ?. s[2] является T, F или цифрой от 0 до 9. s[3] является :. s[4] является T, F или цифрой от 0 до 9. 2⃣Определите вспомогательную функцию solveAtomic(s), которая принимает строку s и возвращает значение атомарного выражения. Значение атомарного выражения равно E1, если B - это T, иначе значение равно E2. Функция будет вызываться только с пятисимвольными строками и возвращать один символ:. 3⃣Если s[0] является T, функция возвращает s[2], иначе возвращает s[4]. В функции parseTernary(expression) уменьшайте выражение до тех пор, пока не останется односимвольная строка. Инициализируйте j как expression.size() - 1 (это будет самый правый индекс окна). Пока самое правое окно длиной 5 не является допустимым атомарным выражением, уменьшайте j на 1. Когда будет найдено самое правое допустимое атомарное выражение, решите его и уменьшите до одного символа. Замените самое правое допустимое атомарное выражение одним символом, после чего длина выражения уменьшится на 4. В итоге останется односимвольная строка, которую и верните. 😎 Решение:
class Solution {
public String parseTernary(String expression) {
boolean isValidAtomic(String s) {
return s.charAt(0) == 'T' || s.charAt(0) == 'F' &&
s.charAt(1) == '?' &&
"TF0123456789".indexOf(s.charAt(2)) != -1 &&
s.charAt(3) == ':' &&
"TF0123456789".indexOf(s.charAt(4)) != -1;
}
char solveAtomic(String s) {
return s.charAt(0) == 'T' ? s.charAt(2) : s.charAt(4);
}
while (expression.length() != 1) {
int j = expression.length() - 1;
while (!isValidAtomic(expression.substring(j-4, j+1))) {
j -= 1;
}
expression = expression.substring(0, j-4) + solveAtomic(expression.substring(j-4, j+1)) + expression.substring(j+1);
}
return expression;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Инфографика в FIGMA с нуля. Курс 0 руб. + портфолио
Онлайн-программа с наставником и чатом. Дизайн от профессионалов. Доступ 0 руб.
Практический марафон по дизайну - легкий старт в digital профессию.
Вас ждут 4 урока, 4 домашних задания, персональный 🎓куратор-эксперт и обратная связь.
Дойдите до конца марафона и пополните оформленное портфолио + сертификат.
Узнать больше
#реклама 16+
yudaevschool24.online
О рекламодателе
6 520
Задача: 946. Validate Stack Sequences
Сложность: medium
Учитывая, что два целочисленных массива pushed и popped имеют разные значения, верните true, если это могло быть результатом последовательности операций push и pop на изначально пустом стеке, или false в противном случае.
Пример:
Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1] Output: true👨💻 Алгоритм: 1⃣Инициализировать пустой стек. Использовать указатель j для отслеживания текущей позиции в массиве popped. 2⃣Пройти по каждому элементу в массиве pushed: Добавить элемент в стек. Проверить верхний элемент стека: Если он совпадает с текущим элементом в popped, удалить элемент из стека и увеличить указатель j. 3⃣В конце вернуть true, если указатель j достиг конца массива popped, иначе вернуть false. 😎 Решение:
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
Stack<Integer> stack = new Stack<>();
int j = 0;
for (int x : pushed) {
stack.push(x);
while (!stack.isEmpty() && j < popped.length && stack.peek() == popped[j]) {
stack.pop();
j++;
}
}
return j == popped.length;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Станьте представителем Т-Банка. Обучим за три дня
Для тех, кто не сидит на месте и любит общаться. Можно устроиться даже без опыта:
— Всему научим и выдадим смартфон
— Будем компенсировать вам расходы на транспорт и оплачивать связь
— Можете работать 2—3 дня или всю неделю
Список вакансий обновляют ежедневно — загляните, что там сегодня
Узнать больше
#реклама
tbank.ru
О рекламодателе
6 520
Задача: 728. Self Dividing Numbers
Сложность: hard
Например, 128 является саморазделяющимся числом, потому что 128 % 1 == 0, 128 % 2 == 0 и 128 % 8 == 0. Саморазделяющееся число не может содержать цифру ноль. Если даны два целых числа left и right, верните список всех саморазделяющихся чисел в диапазоне [left, right].
Пример:
Input: left = 1, right = 22 Output: [1,2,3,4,5,6,7,8,9,11,12,15,22]👨💻 Алгоритм: 1⃣Переберите все числа в диапазоне от left до right. 2⃣Для каждого числа проверьте, является ли оно саморазделяющимся: Разделите число на его цифры. Убедитесь, что ни одна цифра не равна нулю и число делится на каждую из своих цифр без остатка. 3⃣Добавьте саморазделяющиеся числа в результативный список и верните его. 😎 Решение:
import java.util.ArrayList;
import java.util.List;
public class Solution {
public List<Integer> selfDividingNumbers(int left, int right) {
List<Integer> result = new ArrayList<>();
for (int num = left; num <= right; num++) {
if (isSelfDividing(num)) {
result.add(num);
}
}
return result;
}
private boolean isSelfDividing(int num) {
int n = num;
while (n > 0) {
int digit = n % 10;
if (digit == 0 || num % digit != 0) {
return false;
}
n /= 10;
}
return true;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Задача: 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].
Пример:
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.👨💻 Алгоритм: 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-й наименьшей дроби. 😎 Решение:
import java.util.PriorityQueue;
class Solution {
public int[] kthSmallestPrimeFraction(int[] arr, int k) {
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> Double.compare((double)arr[a[0]] / arr[a[1]], (double)arr[b[0]] / arr[b[1]]));
for (int i = 0; i < arr.length - 1; i++) {
pq.offer(new int[]{i, arr.length - 1});
}
for (int i = 0; i < k - 1; i++) {
int[] cur = pq.poll();
if (cur[1] - 1 > cur[0]) {
pq.offer(new int[]{cur[0], cur[1] - 1});
}
}
int[] result = pq.poll();
return new int[]{arr[result[0]], arr[result[1]]};
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Как выйти на доход 100 000+₽ в дизайне с нуля
Забери пошаговый план, как без опыта и связей зарабатывать на дизайне уже через 60 дней по методу обратной интеграции
✅ Без постоянного поиска клиентов
✅ Без бирж и фриланс-площадок
✅ Без продаж и ненужных звонков
✅ И без копеечных заказов по 300 ₽
Бонусы на 100 000 ₽ только для участников:
3 практических курса по Figma, гайды и чек-листы для быстрого старта
Закрытая встреча с арт-директором ТОП3 дизайн студии РФ
Узнай, как с нуля получать реальные заказы и выйти на стабильный доход
Попробовать
#реклама 16+
study.logomachine.ru
О рекламодателе
6 520
Задача: 898. Bitwise ORs of Subarrays
Сложность: medium
Если задан целочисленный массив arr, верните количество различных побитовых ИЛИ всех непустых подмассивов arr. Побитовое ИЛИ подмассива - это побитовое ИЛИ каждого целого числа в подмассиве. Побитовым ИЛИ подмассива одного целого числа является это целое число. Подмассив - это непрерывная непустая последовательность элементов в массиве.
Пример:
Input: arr = [0] Output: 1👨💻 Алгоритм: 1⃣Создать множество для хранения уникальных результатов побитового ИЛИ. 2⃣Для каждого элемента массива, вычислить побитовое ИЛИ всех подмассивов, начинающихся с этого элемента. Добавить результат каждого вычисления в множество. 3⃣Вернуть размер множества. 😎 Решение:
import java.util.*;
class Solution {
public int subarrayBitwiseORs(int[] arr) {
Set<Integer> result = new HashSet<>();
Set<Integer> current = new HashSet<>();
for (int num : arr) {
Set<Integer> next = new HashSet<>();
for (int x : current) {
next.add(x | num);
}
next.add(num);
current = next;
result.addAll(current);
}
return result.size();
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Задача: 971. Flip Binary Tree To Match Preorder Traversal
Сложность: medium
Дано корневое дерево с n узлами, где каждому узлу уникально присвоено значение от 1 до n. Также дана последовательность из n значений voyage, которая является желаемым обходом дерева в порядке pre-order.
Любой узел в бинарном дереве можно перевернуть, поменяв местами его левое и правое поддеревья. Например, переворот узла 1 будет иметь следующий эффект:
Переверните минимальное количество узлов, чтобы обход дерева в порядке pre-order соответствовал voyage.
Верните список значений всех перевернутых узлов. Вы можете вернуть ответ в любом порядке. Если невозможно перевернуть узлы в дереве, чтобы сделать обход в порядке pre-order соответствующим voyage, верните список [-1].
Пример:
Input: root = [1,2], voyage = [2,1] Output: [-1] Explanation: It is impossible to flip the nodes such that the pre-order traversal matches voyage.👨💻 Алгоритм: 1⃣Выполните поиск в глубину. Если в каком-либо узле значение узла не соответствует значению в voyage, верните [-1]. 2⃣Иначе определите, когда нужно перевернуть: если следующее ожидаемое число в voyage (voyage[i]) отличается от следующего потомка. 3⃣Переверните узел, добавьте его значение в список перевернутых узлов и продолжите обход дерева, пока весь порядок обхода pre-order не будет соответствовать voyage. 😎 Решение:
class Solution {
List<Integer> flipped;
int index;
int[] voyage;
public List<Integer> flipMatchVoyage(TreeNode root, int[] voyage) {
flipped = new ArrayList<>();
index = 0;
this.voyage = voyage;
dfs(root);
if (!flipped.isEmpty() && flipped.get(0) == -1) {
flipped = new ArrayList<>(List.of(-1));
}
return flipped;
}
public void dfs(TreeNode node) {
if (node != null) {
if (node.val != voyage[index++]) {
flipped = new ArrayList<>(List.of(-1));
return;
}
if (index < voyage.length && node.left != null && node.left.val != voyage[index]) {
flipped.add(node.val);
dfs(node.right);
dfs(node.left);
} else {
dfs(node.left);
dfs(node.right);
}
}
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Задача: 960. Delete Columns to Make Sorted III
Сложность: hard
Вам дан массив из n строк strs, все одинаковой длины.
Мы можем выбрать любые индексы для удаления, и мы удаляем все символы в этих индексах для каждой строки.
Например, если у нас есть strs = ["abcdef","uvwxyz"] и индексы удаления {0, 2, 3}, то итоговый массив после удаления будет ["bef", "vyz"].
Предположим, мы выбрали набор индексов удаления answer таким образом, что после удаления итоговый массив имеет каждую строку (ряд) в лексикографическом порядке. (т.е. (strs[0][0] <= strs[0][1] <= ... <= strs[0][strs[0].length - 1]) и (strs[1][0] <= strs[1][1] <= ... <= strs[1][strs[1].length - 1]) и так далее). Верните минимально возможное значение answer.length.
Пример:
Input: strs = ["babca","bbazb"] Output: 3 Explanation: After deleting columns 0, 1, and 4, the final array is strs = ["bc", "az"]. Both these rows are individually in lexicographic order (ie. strs[0][0] <= strs[0][1] and strs[1][0] <= strs[1][1]). Note that strs[0] > strs[1] - the array strs is not necessarily in lexicographic order.👨💻 Алгоритм: 1⃣Вместо поиска количества удаляемых столбцов, найдем количество столбцов, которые нужно сохранить. В конце мы можем вычесть это значение, чтобы получить желаемый ответ. 2⃣Используйте динамическое программирование, чтобы решить проблему. Пусть dp[k] будет количеством столбцов, которые сохраняются, начиная с позиции k. Мы будем искать максимальное значение dp[k], чтобы найти количество столбцов, которые нужно сохранить. 3⃣Итоговое количество удаляемых столбцов будет равно общей длине строк минус количество сохраненных столбцов. 😎 Решение:
class Solution {
public int minDeletionSize(String[] A) {
int W = A[0].length();
int[] dp = new int[W];
Arrays.fill(dp, 1);
for (int i = W-2; i >= 0; --i)
search: for (int j = i+1; j < W; ++j) {
for (String row: A)
if (row.charAt(i) > row.charAt(j))
continue search;
dp[i] = Math.max(dp[i], 1 + dp[j]);
}
int kept = 0;
for (int x: dp)
kept = Math.max(kept, x);
return W - kept;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Задача: 459. Repeated Substring Pattern
Сложность: easy
Дана строка s, проверьте, может ли она быть построена путем взятия подстроки и добавления нескольких копий этой подстроки друг за другом.
Пример:
Input: heights = [2,1,5,6,2,3] Output: 10 Explanation: The above is a histogram where width of each bar is 1. The largest rectangle is shown in the red area, which has an area = 10 units.👨💻 Алгоритм: 1⃣Создайте целочисленную переменную n, равную длине строки s. 2⃣Итерация по всем префиксным подстрокам длины i от 1 до n/2: Если i делит n, объявите пустую строку pattern. Используйте внутренний цикл, который выполняется n/i раз для конкатенации подстроки, сформированной из первых i символов строки s. Если pattern равен s, вернуть true. 3⃣Если нет подстроки, которую можно повторить для формирования s, вернуть false. 😎 Решение:
class Solution {
public boolean repeatedSubstringPattern(String s) {
int n = s.length();
for (int i = 1; i <= n / 2; i++) {
if (n % i == 0) {
StringBuilder pattern = new StringBuilder();
for (int j = 0; j < n / i; j++) {
pattern.append(s.substring(0, i));
}
if (s.equals(pattern.toString())) {
return true;
}
}
}
return false;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Задача: 521. Longest Uncommon Subsequence I
Сложность: easy
Даны две строки a и b. Верните длину самой длинной несообщей подпоследовательности между a и b. Если такой несообщей подпоследовательности не существует, верните -1.
Несообщая подпоследовательность между двумя строками — это строка, которая является подпоследовательностью только одной из них.
Пример:
Input: a = "aba", b = "cdc" Output: 3 Explanation: One longest uncommon subsequence is "aba" because "aba" is a subsequence of "aba" but not "cdc". Note that "cdc" is also a longest uncommon subsequence.👨💻 Алгоритм: 1⃣Если строка a равна строке b, верните -1, так как не существует несообщей подпоследовательности. 2⃣В противном случае: Вычислите длины строк a и b. 3⃣Вернуть длину более длинной строки. 😎 Решение:
class Solution {
public int findLUSlength(String a, String b) {
if (a.equals(b)) {
return -1;
} else {
return Math.max(a.length(), b.length());
}
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Задача: CodeTestcaseTest ResultTest Result865. Smallest Subtree with all the Deepest Nodes
Сложность: medium
Дан корень бинарного дерева, глубина каждого узла — это кратчайшее расстояние до корня.
Верните наименьшее поддерево, которое содержит все самые глубокие узлы в исходном дереве.
Узел называется самым глубоким, если у него наибольшая возможная глубина среди всех узлов в дереве.
Поддерево узла — это дерево, состоящее из этого узла и всех его потомков.
Пример:
Input: root = [3,5,1,6,2,0,8,null,null,7,4]
Output: [2,7,4]
Explanation: We return the node with value 2, colored in yellow in the diagram.
The nodes coloured in blue are the deepest nodes of the tree.
Notice that nodes 5, 3 and 2 contain the deepest nodes in the tree but node 2 is the smallest subtree among them, so we return it.
👨💻 Алгоритм:
1⃣В первой фазе используем поиск в глубину (DFS), чтобы аннотировать узлы. Каждый узел будет хранить информацию о своей глубине и о самой большой глубине среди его потомков.
2⃣Во второй фазе также используем DFS для функции answer(node), которая возвращает наименьшее поддерево, содержащее все самые глубокие узлы. Функция сравнивает глубины левых и правых поддеревьев узла для определения наименьшего поддерева.
3⃣Функция answer(node) возвращает поддерево, которое содержит все самые глубокие узлы всего дерева, а не только рассматриваемого поддерева.
😎 Решение:
class Solution {
Map<TreeNode, Integer> depth;
int maxDepth;
public TreeNode subtreeWithAllDeepest(TreeNode root) {
depth = new HashMap<>();
depth.put(null, -1);
dfs(root, null);
maxDepth = depth.values().stream().max(Integer::compare).orElse(-1);
return answer(root);
}
private void dfs(TreeNode node, TreeNode parent) {
if (node != null) {
depth.put(node, depth.get(parent) + 1);
dfs(node.left, node);
dfs(node.right, node);
}
}
private TreeNode answer(TreeNode node) {
if (node == null || depth.get(node) == maxDepth) return node;
TreeNode L = answer(node.left), R = answer(node.right);
if (L != null && R != null) return node;
return L != null ? L : R;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Изучите HTML и CSS - бесплатно!
Попробуйте бесплатно — освоите базу HTML & CSS, создадите свою первую веб страницу и поймете, стоит ли погружаться в IT глубже.
Почему стоит попробовать?
- Никакой воды — только практика
- Проверь профессию до того, как вложить в обучение 150+ тыс.
- Убедитесь, что код — это не страшно, даже если раньше не получалось
А чтобы у вас все получилось, мы добавили бонусы:
✅ 8 пошаговых гайдов — от первого кода до первых заработков в IT.
✅ До 1500 монет за задания, которые можно обменять на дальнейшее обучение.
✅ Закрытый чат с наставником — получите ответы на все вопросы.
✅ Полезный IT-канал в Telegram — оставайтесь в теме после курса.
⚡ Главное — вы попробуете профессию разработчика!
Попробовать
#реклама 16+
learn.result-university.com
О рекламодателе
6 520
Задача: 813. Largest Sum of Averages
Сложность: medium
Вам дан целочисленный массив nums и целое число k. Вы можете разбить массив на не более чем k непустых смежных подмассивов. Оценка разбиения равна сумме средних значений каждого подмассива.
Обратите внимание, что при разбиении должны быть использованы все целые числа из nums, и что оценка не обязательно является целым числом.
Верните максимальную оценку, которую можно достичь среди всех возможных разбиений. Ответы, отличающиеся от фактического ответа не более чем на 10^-6, будут приняты.
Пример:
Input: nums = [9,1,2,3,9], k = 3 Output: 20.00000 Explanation: The best choice is to partition nums into [9], [1, 2, 3], [9]. The answer is 9 + (1 + 2 + 3) / 3 + 9 = 20. We could have also partitioned nums into [9, 1], [2], [3, 9], for example. That partition would lead to a score of 5 + 2 + 6 = 13, which is worse.👨💻 Алгоритм: 1⃣Пусть dp(i, k) будет лучшей оценкой для разбиения массива A[i:] на не более чем k частей. Если первая группа, в которую мы разбиваем A[i:], заканчивается перед j, тогда наше разбиение-кандидат имеет оценку average(i, j) + dp(j, k-1), где average(i, j) = (A[i] + A[i+1] + ... + A[j-1]) / (j - i) (деление с плавающей запятой). Мы берем наивысшую оценку из этих вариантов, помня, что разбиение необязательно - dp(i, k) также может быть просто average(i, N). 2⃣В общем случае наша рекурсия выглядит так: dp(i, k) = max(average(i, N), max_{j > i}(average(i, j) + dp(j, k-1))). Мы можем рассчитывать average немного быстрее, используя префиксные суммы. Если P[x+1] = A[0] + A[1] + ... + A[x], тогда average(i, j) = (P[j] - P[i]) / (j - i). 3⃣Наша реализация демонстрирует подход "снизу вверх" для динамического программирования. На шаге k во внешнем цикле, dp[i] представляет собой dp(i, k) из обсуждения выше, и мы рассчитываем следующий слой dp(i, k+1). Завершение второго цикла для i = 0..N-1 означает завершение расчета правильного значения для dp(i, t), а внутренний цикл выполняет расчет max_{j > i}(average(i, j) + dp(j, k)). 😎 Решение:
class Solution {
public double largestSumOfAverages(int[] A, int K) {
int N = A.length;
double[] P = new double[N + 1];
for (int i = 0; i < N; ++i)
P[i + 1] = P[i] + A[i];
double[][] dp = new double[N][N];
for (int i = 0; i < N; ++i)
dp[i][0] = (P[N] - P[i]) / (N - i);
for (int k = 0; k < K - 1; ++k) {
for (int i = 0; i < N; ++i) {
for (int j = i + 1; j < N; ++j) {
dp[i][0] = Math.max(dp[i][0], (P[j] - P[i]) / (j - i) + dp[j][0]);
}
}
}
return dp[0][0];
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Задача: 392. Is Subsequence
Сложность: easy
Даны две строки s и t. Верните true, если s является подпоследовательностью t, иначе верните false.
Подпоследовательность строки — это новая строка, которая формируется из исходной строки путем удаления некоторых (возможно, ни одного) символов без нарушения относительных позиций оставшихся символов. (например, "ace" является подпоследовательностью "abcde", тогда как "aec" не является).
Пример:
Input: s = "abc", t = "ahbgdc" Output: true👨💻 Алгоритм: 1⃣Назначьте два указателя: левый для исходной строки и правый для целевой строки. Эти указатели будут использоваться для итерации по строкам и сравнения их символов. 2⃣Перемещайте указатели в зависимости от совпадения символов. Если символы на текущих позициях указателей совпадают, переместите оба указателя на один шаг вперед. Если символы не совпадают, переместите только правый указатель целевой строки. 3⃣Итерация завершается, когда один из указателей выходит за пределы своей строки. Если в конце итерации все символы исходной строки были найдены в целевой строке, исходная строка является подпоследовательностью целевой строки. 😎 Решение:
class Solution {
public boolean isSubsequence(String s, String t) {
int leftBound = s.length(), rightBound = t.length();
int pLeft = 0, pRight = 0;
while (pLeft < leftBound && pRight < rightBound) {
if (s.charAt(pLeft) == t.charAt(pRight)) {
pLeft += 1;
}
pRight += 1;
}
return pLeft == leftBound;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 520
Дизайн в FIGMA с нуля. Бесплатный курс + портфолио
Онлайн-программа с наставником и чатом. Дизайн от профессионалов. Доступ 0 руб.
Узнать больше
#реклама 16+
yudaevschool24.online
О рекламодателе
