Java | LeetCode
الذهاب إلى القناة على Telegram
Cайт easyoffer.ru Реклама @easyoffer_adv ВП @easyoffer_vp Тесты t.me/+icUwivvbGOkwNWRi Вопросы собесов t.me/+7ESm0VKXC4tjYzky Вакансии t.me/+4pspF5nDjgM4MjQy
إظهار المزيد6 656
المشتركون
-124 ساعات
-157 أيام
-5130 أيام
أرشيف المشاركات
6 655
Задача: 94. Binary Tree Inorder Traversal
Сложность: easy
Дан корень бинарного дерева. Верните обход значений его узлов в симметричном порядке.
Пример:
Input: root = [1,null,2,3] Output: [1,3,2]👨💻 Алгоритм: 1⃣Создаём вспомогательную функцию helper, которая будет рекурсивно обходить дерево. 2⃣В каждом узле сначала рекурсивно вызываем helper для левого поддерева. 3⃣После левого поддерева добавляем значение текущего узла в список, затем переходим к правому поддереву. 😎 Решение:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
helper(root, res);
return res;
}
public void helper(TreeNode root, List<Integer> res) {
if (root != null) {
helper(root.left, res);
res.add(root.val);
helper(root.right, res);
}
}
}
Ставь 👍 и забирай 📚 Базу знаний6 655
+4
⚡️ Linux теперь в Telegram!
Ребята сделали крутейший канал про Linux, где на простых картинках и понятном языке обучают работе с этой ОС, делятся полезными фишками и инструментами
Подписывайтесь: @linuxos_tg
6 655
Repost from easyoffer
🚨 Последний шанс!
Сегодня — последний день краудфандинга.
Через несколько часов всё закроется, и больше невозможно будет поучаствовать.
Если ты хотел, но откладывал — СЕЙЧАС самое время. Займёт 2 минуты, но изменит твой подход к собеседованиям надолго.
Поддержи easyoffer 2.0 и получи:
🚀 PRO подписка к easyoffer 2.0 на 1 год по цене месячной подписки. Активировать подписку можно в любой момент, например, когда начнешь искать работу. ➕ Приглашение на закрытое бета-тестирование
PRO подписка к easyoffer 2.0:
✅ Доступ к списку вопросов, которые задаются на собеседованиях + вероятность встречи этих вопросов + их фильтрация по грейдам, типам интервью, компаниям
✅ Доступ к лучшим ответам на вопросы
✅ Список самых частых задач, которые задаются на собеседовании + их фильтрация по грейдам и компаниям
✅ Доступ к лучшим ответам на задачи
✅ Список тестовых заданий компаний + лучшее решение
✅ Доступ к тренажеру "Проработка вопросов", который позволит очень быстро подготовиться к самым частым вопросам
✅ Доступ к тренажеру "Реальное собеседование", который позволит тренироваться проходить собеседование в конкретную компанию
До конца кампании — остались часы.
Поддержать: https://planeta.ru/campaigns/easyoffer
📌 Если не получается оплатить через карту РФ — напишите мне @kivaiko, и мы найдём удобный способ
6 655
Ищешь высокооплачиваемые проекты? Попробуй SkillStaff
SkillStaff — это платформа для ИТ-специалистов, менеджеров и креаторов, которым мало одного оклада. Здесь можно найти клиентов, выполнять их проекты и увеличивать свой доход.
- Проекты с гибким графиком: part time, full time, удаленка и гибрид
- Ставка за час работы — та, что ты сам выбрал
- Клиенты — ведущие бренды, проверенные с юридической точки зрения при регистрации на платформе
- Оплата поступает ежемесячно на расчетный счет исполнителя
- Удобный личный кабинет и функционал, автоматизирующий документооборот
Все, что нужно для работы — иметь статус самозанятого или ИП, а платформа поможет со всеми нюансами.
Регистрируйся прямо сейчас
Зарегистрироваться
#реклама 16+
skillstaff.ru
О рекламодателе
6 655
Задача: 138. Copy List with Random Pointer
Сложность: medium
Дан связный список длиной n, в котором каждый узел содержит дополнительный случайный указатель (random pointer), который может указывать на любой узел в списке или быть равным null.
Создайте глубокую копию списка. Глубокая копия должна состоять из ровно n совершенно новых узлов, где каждый новый узел имеет значение, равное значению соответствующего оригинального узла. Указатели next и random новых узлов должны указывать на новые узлы в скопированном списке таким образом, чтобы указатели в оригинальном и скопированном списке представляли одно и то же состояние списка. Ни один из указателей в новом списке не должен указывать на узлы в оригинальном списке.
Например, если в оригинальном списке есть два узла X и Y, где X.random --> Y, то для соответствующих узлов x и y в скопированном списке, x.random должен указывать на y.
Верните голову скопированного связного списка.
Связный список представлен во входных/выходных данных как список из n узлов. Каждый узел представлен парой [val, random_index], где:
val: целое число, представляющее Node.val
random_index: индекс узла (в диапазоне от 0 до n-1), на который указывает случайный указатель, или null, если он не указывает ни на какой узел.
Вашему коду будет дана только голова оригинального связного списка.
Пример:
Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]] Output: [[7,null],[13,0],[11,4],[10,2],[1,0]]👨💻 Алгоритм: 1⃣Инициализация и начало обхода: Начните обход графа со стартового узла (head). Создайте словарь visited_dictionary для отслеживания посещенных и клонированных узлов. 2⃣Проверка и клонирование узлов: Для каждого текущего узла (current_node) проверьте, есть ли уже клонированная копия в visited_dictionary. Если клонированная копия существует, используйте ссылку на этот клонированный узел. Если клонированной копии нет, создайте новый узел (cloned_node_for_current_node), инициализируйте его и добавьте в visited_dictionary, где ключом будет current_node, а значением — созданный клон. 3⃣Рекурсивные вызовы для обработки связей: Сделайте два рекурсивных вызова для каждого узла: один используя указатель random, другой — указатель next. Эти вызовы отражают обработку "детей" текущего узла в терминах графа, где детьми являются узлы, на которые указывают указатели random и next. 😎 Решение:
public class Solution {
HashMap<Node, Node> visitedHash = new HashMap<Node, Node>();
public Node copyRandomList(Node head) {
if (head == null) {
return null;
}
if (this.visitedHash.containsKey(head)) {
return this.visitedHash.get(head);
}
Node node = new Node(head.val, null, null);
this.visitedHash.put(head, node);
node.next = this.copyRandomList(head.next);
node.random = this.copyRandomList(head.random);
return node;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 655
Repost from easyoffer
Завтра последний день!
Краудфандинг заканчивается уже завтра, и второй попытки не будет.
👉 Поддержи easyoffer 2.0 и получи:
🚀 PRO подписка к easyoffer 2.0 на 1 год по цене месячной подписки. Активировать подписку можно в любой момент, например, когда начнешь искать работу. ➕ Приглашение на закрытое бета-тестирование
📌 Если не получается оплатить через карту РФ — напишите мне @kivaiko, и мы найдём удобный способ
6 655
Задача: 147. Insertion Sort List
Сложность: medium
Дана голова односвязного списка. Отсортируйте список, используя сортировку вставками, и верните голову отсортированного списка.
Шаги алгоритма сортировки вставками:
1. Сортировка вставками итеративно работает, потребляя один входной элемент за каждую итерацию и формируя отсортированный выходной список.
2. На каждой итерации сортировка вставками удаляет один элемент из входных данных, находит место, куда он принадлежит в отсортированном списке, и вставляет его туда.
3. Процесс повторяется до тех пор, пока не закончатся входные элементы.
Пример:
Input: head = [4,2,1,3] Output: [1,2,3,4]👨💻 Алгоритм: 1⃣Создание вспомогательного узла (pseudo_head): В качестве первого шага создайте вспомогательный узел, который называется pseudo_head. Этот узел будет использоваться как указатель на начало результирующего списка. Этот узел облегчает доступ к результирующему списку, особенно когда необходимо вставить новый элемент в начало списка. Этот прием значительно упрощает логику работы с односвязным списком. 2⃣Механизм вставки узла: В односвязном списке каждый узел содержит только один указатель, который указывает на следующий узел. Чтобы вставить новый узел (например, B) перед определенным узлом (например, A), необходимо знать узел (например, C), который находится перед узлом A (т.е. C -> A). Имея ссылку на узел C, можно вставить новый узел так, чтобы получилось C -> B -> A. 3⃣Использование пары указателей для вставки: Используя пару указателей (prev и next), которые служат местом для вставки нового элемента между ними, вставьте новый элемент в список. Это делается путем установки prev -> new_node -> next. Этот метод позволяет точно и безопасно вставлять новые элементы в список, сохраняя при этом правильный порядок элементов без необходимости перемещения других узлов списка. 😎 Решение:
class Solution {
public ListNode insertionSortList(ListNode head) {
ListNode dummy = new ListNode();
ListNode curr = head;
while (curr != null) {
ListNode prev = dummy;
while (prev.next != null && prev.next.val <= curr.val) {
prev = prev.next;
}
ListNode next = curr.next;
curr.next = prev.next;
prev.next = curr;
curr = next;
}
return dummy.next;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 655
Высшее образование онлайн — поменяйте жизнь в 2025 году!
✅Набор в апреле: от 6700 ₽/мес.*
Московский технологический институт предлагает:
— Высшее образование в московском вузе без выезда на сессии
— Полностью дистанционный онлайн-формат
— Возможность обучаться дома, на работе, в путешествии
— Диплом государственного образца
— Более 60 направлений на выбор (IT, инженерные, экономические, педагогические, управленческие и другие)
— 5 способов оплаты обучения
— Поддержка персонального куратора: от поступления до получения диплома
Узнать больше
#реклама 16+
mti-vuz.ru
О рекламодателе
6 655
Задача: 1129. Shortest Path with Alternating Colors
Сложность: medium
Вам дано целое число n, количество узлов в ориентированном графе, где узлы помечены от 0 до n - 1. Каждое ребро в этом графе может быть красным или синим, и могут быть самопетли и параллельные ребра.
Вам даны два массива redEdges и blueEdges, где:
redEdges[i] = [ai, bi] указывает, что в графе существует направленное красное ребро от узла ai к узлу bi, и
blueEdges[j] = [uj, vj] указывает, что в графе существует направленное синее ребро от узла uj к узлу vj.
Верните массив answer длины n, где каждый answer[x] — это длина кратчайшего пути от узла 0 до узла x, такого что цвета ребер чередуются вдоль пути, или -1, если такого пути не существует.
Пример:
Input: n = 3, redEdges = [[0,1],[1,2]], blueEdges = [] Output: [0,1,-1]👨💻 Алгоритм: 1⃣Создание структуры данных и инициализация: Создайте список смежности adj, который будет содержать пары (сосед, цвет) для каждого узла. Создайте массив answer длиной n, инициализированный значением -1, чтобы хранить длину кратчайшего пути для каждого узла. Создайте 2D массив visit для отслеживания, были ли узлы посещены с использованием ребра определённого цвета. 2⃣Инициализация очереди и начальных условий: Создайте очередь для хранения трёх значений (узел, количество шагов, цвет предыдущего ребра). Добавьте в очередь начальный узел (0, 0, -1) и установите visit[0][0] и visit[0][1] в true, так как повторное посещение узла 0 бессмысленно. 3⃣Обработка очереди и обновление результата: Пока очередь не пуста, извлекайте элемент из очереди и получайте (узел, количество шагов, цвет предыдущего ребра). Для каждого соседа, если сосед не был посещён с использованием ребра текущего цвета и текущий цвет не равен предыдущему, обновите массив answer и добавьте соседа в очередь. 😎 Решение:
class Solution {
public int[] shortestAlternatingPaths(int n, int[][] redEdges, int[][] blueEdges) {
Map<Integer, List<List<Integer>>> adj = new HashMap<>();
for (int[] redEdge : redEdges) {
adj.computeIfAbsent(redEdge[0], k -> new ArrayList<List<Integer>>()).add(
Arrays.asList(redEdge[1], 0));
}
for (int[] blueEdge : blueEdges) {
adj.computeIfAbsent(blueEdge[0], k -> new ArrayList<List<Integer>>()).add(
Arrays.asList(blueEdge[1], 1));
}
int[] answer = new int[n];
Arrays.fill(answer, -1);
boolean[][] visit = new boolean[n][2];
Queue<int[]> q = new LinkedList<>();
q.offer(new int[] { 0, 0, -1 });
answer[0] = 0;
visit[0][1] = visit[0][0] = true;
while (!q.isEmpty()) {
int[] element = q.poll();
int node = element[0], steps = element[1], prevColor = element[2];
if (!adj.containsKey(node)) {
continue;
}
for (List<Integer> nei : adj.get(node)) {
int neighbor = nei.get(0);
int color = nei.get(1);
if (!visit[neighbor][color] && color != prevColor) {
if (answer[neighbor] == -1)
answer[neighbor] = 1 + steps;
visit[neighbor][color] = true;
q.offer(new int[] { neighbor, 1 + steps, color });
}
}
}
return answer;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 655
Repost from easyoffer
⏳ Осталось 3 дня!
Финальный отсчёт пошёл — осталось всего 3 дня до окончания краудфандинга easyoffer 2.0
Сейчас можно получить максимум пользы за минимальные деньги. После окончания кампании цены вырастут и вознаграждения станут недоступны.
👉 Поддержи easyoffer 2.0 и получи:
🚀 PRO подписка к easyoffer 2.0 на 1 год по цене месячной подписки. Активировать подписку можно в любой момент, например, когда начнешь искать работу. ➕ Приглашение на закрытое бета-тестирование
Поддержи проект сейчас, чтобы не забыть!
📌 Если не получается оплатить через карту РФ — напишите мне @kivaiko, и мы найдём удобный способ
6 655
Освойте профессию Системный аналитик с нуля за 7 месяцев
Освойте высокооплачиваемую IT-профессию без программирования. Выдаём диплом, помогаем с трудоустройством.
Excel, BPMN, UML, Python, SQL, API
Преимущества обучения в Академии Eduson:
🎓 22 реальных бизнес-кейса
🎓 официальный государственный диплом
🎓 рассрочка 0% на 24 мес.
🎓 бессрочный доступ к лекциям и материалам, которые регулярно обновляются
🎓 личный куратор с Вами на связи
Начните обучаться онлайн и получать доход уже во время обучения!
Получить скидку
#реклама 16+
mrqz.me
О рекламодателе
6 655
Задача: 151. Reverse Words in a String
Сложность: medium
Дана входная строка s, переверните порядок слов.
Слово определяется как последовательность символов, не являющихся пробелами. Слова в строке s разделены как минимум одним пробелом.
Верните строку, в которой слова расположены в обратном порядке, соединённые одним пробелом.
Обратите внимание, что строка s может содержать пробелы в начале или в конце, или множественные пробелы между двумя словами. Возвращаемая строка должна содержать только один пробел, разделяющий слова. Не включайте лишние пробелы.
Пример:
Input: s = "the sky is blue" Output: "blue is sky the"👨💻 Алгоритм: 1⃣Удаление лишних пробелов: Удалите начальные и конечные пробелы из строки s. Это делается для того, чтобы убрать пробелы в начале и в конце строки, которые могут исказить конечный результат. В коде это реализовано с помощью методов erase и find_first_not_of/find_last_not_of, которые удаляют пробелы до первого и после последнего непробельного символа. 2⃣Разделение строки на слова: Преобразуйте строку s в поток и используйте istringstream для чтения слов, разделенных пробелами. Каждое слово определяется как последовательность символов, не содержащая пробелов. Слова сохраняются в вектор words. Это делается с помощью copy, который копирует слова из потока в words с помощью istream_iterator. 3⃣Реверсирование и соединение слов: Переверните вектор слов и соедините их обратно в одну строку, разделяя слова одним пробелом. Для реверсирования используется функция reverse, а для соединения слов — ostringstream вместе с ostream_iterator. Слова объединяются таким образом, что между ними находится только один пробел, исключая лишние пробелы между словами. 😎 Решение:
class Solution {
public String reverseWords(String s) {
s = s.trim();
List<String> wordList = Arrays.asList(s.split("\\s+"));
Collections.reverse(wordList);
return String.join(" ", wordList);
}
}
Ставь 👍 и забирай 📚 Базу знаний6 655
Профессия «Аналитик данных» - начни учиться бесплатно!
Освойте высокооплачиваемую IT-профессию с нуля за 6 месяцев. Выдаём диплом, помогаем с трудоустройством.
Excel, SQL, PowerBI, Python.
Преимущества обучения в Академии Eduson:
🎓 можно начать учиться бесплатно, если не понравится — не платите
🎓 официальный государственный диплом
🎓 рассрочка 0% на 24 мес.
🎓 бессрочный доступ к лекциям и материалам, которые регулярно обновляются
🎓 личный куратор с Вами на связи
Начните обучаться онлайн и получать стабильный доход уже во время обучения!
Узнать больше
#реклама 16+
eduson.academy
О рекламодателе
6 655
Задача: 1074. Number of Submatrices That Sum to Target
Сложность: hard
Дана матрица и целевое значение. Верните количество непустых подматриц, сумма элементов которых равна целевому значению.
Подматрица x1, y1, x2, y2 — это набор всех ячеек matrix[x][y] с x1 <= x <= x2 и y1 <= y <= y2.
Две подматрицы (x1, y1, x2, y2) и (x1', y1', x2', y2') различны, если у них есть какая-то различающаяся координата: например, если x1 != x1'.
Пример:
Input: matrix = [[0,1,0],[1,1,1],[0,1,0]], target = 0
Output: 4
Explanation: The four 1x1 submatrices that only contain 0.
👨💻 Алгоритм:
1⃣Инициализируйте результат: count = 0. Вычислите количество строк: r = len(matrix) и количество столбцов: c = len(matrix[0]). Вычислите двумерную префиксную сумму ps, выделив еще одну строку и еще один столбец для нулевых значений.
2⃣Итерируйте по строкам: r1 от 1 до r и r2 от r1 до r. Внутри этого двойного цикла фиксируйте левые и правые границы строк и инициализируйте хэш-таблицу для хранения префиксных сумм. Итерируйте по столбцам от 1 до c + 1, вычислите текущую префиксную сумму 1D curr_sum и увеличьте count на количество матриц, сумма которых равна target.
3⃣Добавьте текущую префиксную сумму 1D в хэш-таблицу. Когда все итерации завершены, верните count.
😎 Решение:
class Solution {
public int numSubmatrixSumTarget(int[][] matrix, int target) {
int r = matrix.length, c = matrix[0].length;
int[][] ps = new int[r + 1][c + 1];
for (int i = 1; i < r + 1; ++i) {
for (int j = 1; j < c + 1; ++j) {
ps[i][j] = ps[i - 1][j] + ps[i][j - 1] - ps[i - 1][j - 1] + matrix[i - 1][j - 1];
}
}
int count = 0, currSum;
Map<Integer, Integer> h = new HashMap();
for (int r1 = 1; r1 < r + 1; ++r1) {
for (int r2 = r1; r2 < r + 1; ++r2) {
h.clear();
h.put(0, 1);
for (int col = 1; col < c + 1; ++col) {
currSum = ps[r2][col] - ps[r1 - 1][col];
count += h.getOrDefault(currSum - target, 0);
h.put(currSum, h.getOrDefault(currSum, 0) + 1);
}
}
}
return count;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 655
Repost from easyoffer
Офигеть, вот это поддержка! 🔥
Скажу честно: когда я планировал запуск краудфандинговой кампании, в голове были разные варианты развития событий. Думал — ну, наверное, получится собрать 300 тысяч. В самом идеальном сценарии — может быть, миллион.
Но больше всего я боялся, что запущу кампанию, и не получится собрать даже 300 т. Это был бы провал. Так много усилий, времени и денег вложено в проект… и если бы всё закончилось ничем — это бы сильно демотивировало.
Но, ребята, мы превысили изначальную цель в 10 раз —
3 031 040 рублей! 🤯
Вся эта кампания — это одна большая проверка бизнес-модели на прочность. И я супер рад, что запустил всё публично. Люди видят, что EasyOffer реально нужен. Теперь нет сомнений — проект актуален, он будет прибыльным и будет развиваться.
Мне приходит огромное количество сообщений в личку: кто-то когда-то давно пользовался сайтом, он помог с трудоустройством, и сейчас они уже не ищут работу — но всё равно поддержали.
Это прям очень круто и трогательно.
Никак не могу отделаться от мысли, что easyoffer — это ведь мой первый сайт. Учебный, пет-проект, просто для портфолио. И вот что из него вышло. Просто офигеть.
Я не зря ушёл с работы, чтобы заниматься только им.
Я поверил в этот проект — и сейчас вижу, что вы тоже в него верите. Для меня это очень многое значит.
Огромное спасибо за вашу поддержку! ❤️
6 655
Задача: 110. Balanced Binary Tree
Сложность: easy
Дано бинарное дерево, определите, является ли оно
сбалансированным по высоте.
Пример:
Input: root = [3,9,20,null,null,15,7] Output: true👨💻 Алгоритм: 1⃣Сначала мы определяем функцию height, которая для любого узла p в дереве T возвращает: -1, если p является пустым поддеревом, т.е. null; 1 + max(height(p.left), height(p.right)) в противном случае. 2⃣Теперь, когда у нас есть метод для определения высоты дерева, остается только сравнить высоты детей каждого узла. Дерево T с корнем r является сбалансированным тогда и только тогда, когда высоты его двух детей отличаются не более чем на 1 и поддеревья каждого ребенка также сбалансированы. 3⃣Следовательно, мы можем сравнить высоты двух дочерних поддеревьев, а затем рекурсивно проверить каждое из них: Если root == NULL, возвращаем true. Если abs(height(root.left) - height(root.right)) > 1, возвращаем false. В противном случае возвращаем isBalanced(root.left) && isBalanced(root.right). 😎 Решение:
class Solution {
private int height(TreeNode root) {
if (root == null) {
return -1;
}
return 1 + Math.max(height(root.left), height(root.right));
}
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
return (
Math.abs(height(root.left) - height(root.right)) < 2 &&
isBalanced(root.left) &&
isBalanced(root.right)
);
}
}
Ставь 👍 и забирай 📚 Базу знаний6 655
Крупнейший университет искусственного интеллекта
Учим использовать ChatGPT в профессиональных целях, создавать нейро-сотрудников и зарабатывать на искусственном интеллекте.
✨ 8 000+ студентов со всего мира
✨ 600+ AI-проектов, созданных студентами
✨ Сборная Университета — победители крупнейших AI-хакатонов России
✨ Стажировки в крупнейших компаниях России (РЖД, Ростелеком, РУДН, Совкомбанк, Самолет и другие)
✨ Трудоустраиваем выпускников в крупнейшие компании (Яндекс, ВТБ, Сбербанк, Роскосмос и другие)
Будем рады видеть тебя в наших рядах!
Узнать больше
#реклама 16+
neural-university.ru
О рекламодателе
6 655
Задача: 1168. Optimize Water Distribution in a Village
Сложность: hard
В деревне есть n домов. Мы хотим обеспечить все дома водой, строя колодцы и прокладывая трубы.
Для каждого дома i мы можем либо построить колодец внутри него непосредственно с затратами wells[i - 1] (обратите внимание на -1 из-за нумерации с нуля), либо провести воду из другого колодца с помощью трубы. Затраты на прокладку труб между домами даны в массиве pipes, где каждый pipes[j] = [house1j, house2j, costj] представляет собой стоимость соединения дома house1j и дома house2j с помощью трубы. Соединения двунаправленные, и между одними и теми же домами могут быть несколько допустимых соединений с разными затратами.
Верните минимальные оhttps://leetcode.com/problems/optimize-water-distribution-in-a-village/Figures/1168/PrimAlgDemo.gifбщие затраты на обеспечение всех домов водой.
Пример:
Input: n = 3, wells = [1,2,2], pipes = [[1,2,1],[2,3,1]]
Output: 3
Explanation: The image shows the costs of connecting houses using pipes.
The best strategy is to build a well in the first house with cost 1 and connect the other houses to it with cost 2 so the total cost is 3.
👨💻 Алгоритм:
1⃣Представление графа: Постройте список смежности для представления графа, где вершины и ребра соответствуют домам и трубам. Список смежности можно представить в виде списка списков или словаря списков.
2⃣Набор для вершин: Используйте набор для поддержания всех вершин, добавленных в окончательное минимальное остовное дерево (MST) во время его построения. С помощью набора можно определить, была ли вершина уже добавлена или нет.
3⃣Очередь с приоритетом (куча): Используйте кучу для реализации жадной стратегии. На каждом шаге определяйте лучшее ребро для добавления на основе стоимости его добавления в дерево. Куча позволяет извлекать минимальный элемент за константное время и удалять минимальный элемент за логарифмическое время. Это идеально подходит для нашей задачи повторного нахождения ребра с наименьшей стоимостью.
😎 Решение:
class Solution {
public int minCostToSupplyWater(int n, int[] wells, int[][] pipes) {
PriorityQueue<int[]> edgesHeap = new PriorityQueue<>((a, b) -> a[0] - b[0]);
List<List<int[]>> graph = new ArrayList<>(n + 1);
for (int i = 0; i < n + 1; ++i) {
graph.add(new ArrayList<>());
}
for (int i = 0; i < wells.length; ++i) {
graph.get(0).add(new int[]{wells[i], i + 1});
edgesHeap.add(new int[]{wells[i], i + 1});
}
for (int[] pipe : pipes) {
int house1 = pipe[0];
int house2 = pipe[1];
int cost = pipe[2];
graph.get(house1).add(new int[]{cost, house2});
graph.get(house2).add(new int[]{cost, house1});
}
Set<Integer> mstSet = new HashSet<>();
mstSet.add(0);
int totalCost = 0;
while (mstSet.size() < n + 1) {
int[] edge = edgesHeap.poll();
int cost = edge[0];
int nextHouse = edge[1];
if (mstSet.contains(nextHouse)) continue;
mstSet.add(nextHouse);
totalCost += cost;
for (int[] neighborEdge : graph.get(nextHouse)) {
if (!mstSet.contains(neighborEdge[1])) {
edgesHeap.add(neighborEdge);
}
}
}
return totalCost;
}
}
Ставь 👍 и забирай 📚 Базу знаний6 655
Сделайте рывок в карьере Frontend за 3 месяца!
Не понимаете как правильно учиться, много знаний, но нет четкой структуры в голове?
Не можете запомнить разницу между merge и rebase? Вроде бы все знаете в теории, но не можете написать простую программу/приложение и не знаете куда применить полученные знания?
Приходите на эфир и узнайте:
Как структурировать знания и избавиться от хаотичного потребления информации, составим четкий план вашего развития.
Затронем тему выгорания на длинной дистанции и как преодолеть страх пробелов в знаниях и почему вы забрасываете учёбу на полпути.
И на последок узнаете как получить заветный оффер и при этом иметь практический опыт коммерческой разработки с сильным проектом, который не обойдет ни один HR.
Записаться
#реклама 16+
salebot.site
О рекламодателе
6 655
Задача: 994. Rotting Oranges
Сложность: medium
Дан m x n сетка, где каждая ячейка может иметь одно из трех значений:
0, представляющее пустую ячейку,
1, представляющее свежий апельсин,
2, представляющее гнилой апельсин.
Каждую минуту любой свежий апельсин, который находится в 4-х направленно смежной ячейке с гнилым апельсином, становится гнилым.
Верните минимальное количество минут, которые должны пройти, пока в ячейке не останется свежих апельсинов. Если это невозможно, верните -1.
Пример:
Input: grid = [[2,1,1],[0,1,1],[1,0,1]] Output: -1 Explanation: The orange in the bottom left corner (row 2, column 0) is never rotten, because rotting only happens 4-directionally.👨💻 Алгоритм: 1⃣Инициализация очереди и подсчет апельсинов: Пройдите по всей сетке, добавьте все гнилые апельсины в очередь и подсчитайте общее количество свежих апельсинов. Если нет свежих апельсинов, верните 0. 2⃣Использование BFS для распространения гнили: Выполняйте BFS, начиная с всех гнилых апельсинов, добавленных в очередь. Каждый раз, когда апельсин становится гнилым, уменьшайте счетчик свежих апельсинов. Если свежих апельсинов больше не осталось, верните текущее количество минут. 3⃣Проверка оставшихся свежих апельсинов: Если после завершения BFS все еще остаются свежие апельсины, верните -1. 😎 Решение:
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
public int orangesRotting(int[][] grid) {
Queue<int[]> queue = new LinkedList<>();
int freshCount = 0;
int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j] == 2) {
queue.offer(new int[]{i, j});
} else if (grid[i][j] == 1) {
freshCount++;
}
}
}
if (freshCount == 0) return 0;
int minutes = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
int[] point = queue.poll();
for (int[] dir : directions) {
int ni = point[0] + dir[0], nj = point[1] + dir[1];
if (ni >= 0 && ni < grid.length && nj >= 0 && nj < grid[0].length && grid[ni][nj] == 1) {
grid[ni][nj] = 2;
freshCount--;
queue.offer(new int[]{ni, nj});
}
}
}
if (!queue.isEmpty()) {
minutes++;
}
}
return freshCount == 0 ? minutes : -1;
}
}
Ставь 👍 и забирай 📚 Базу знаний
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
