Java Algorithms
111 subscribers
625 photos
623 links
Добро пожаловать💡

Канал для всех, кто ищет качественные решения и объяснения задач на Java

Roadmap по каналу:
https://t.me/algoroadmap/2
Download Telegram
🔴Hard
295. Find Median from Data Stream

Company: 📕📱🚖

📝Реализуйте класс MedianFinder:

MedianFinder() инициализирует MedianFinder объект
void addNum(int num) добавляет целое число num из потока данных в структуру данных
double findMedian() возвращает медиану всех элементов на данный момент

Медиана — это среднее значение в упорядоченном целочисленном списке. Если размер списка четный, медиана — это среднее значение двух средних значений

💡: используйте две очереди — для левой и правой половины потока чисел

#leetcode295 | #hard #priorityqueue
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 295

Time: O(log(n))
Space: O(n)

💡 Идея
🟦Для реализации используем две приоритетные очереди: left — содержащую левую половину чисел с приоритетом на большие значения, right — содержащую правую половину чисел с приоритетом на меньшие значения

🟦Благодаря такому разделению медиана всегда будет находиться либо на вершине одной из очередей, либо как среднее значение между вершинами двух очередей

🟦При добавлении нового числа всегда сначала кладем его в left, затем выполняем корректировку:
если верхнее значение left больше наименьшего значения right или если разница в размерах куч превышает 1 — элементы перемещаются между очередями для поддержания баланса

🟦Медиану определяем в зависимости от размера очередей:
если обе кучи равны по размеру, медиана — это среднее значение двух центральных элементов (вершин очередей)
если одна очередь больше другой по размеру, медиана — это вершина большей очереди

🟦Благодаря сбалансированной структуре, поиск медианы занимает O(1), а добавление числа — O(log n), что делает алгоритм эффективным для больших потоков данных

👩‍💻 Java Algo | #solution295
Please open Telegram to view this post
VIEW IN TELEGRAM
Стартуем тему Backtracking

Представь, что ты оказался в огромном замке, полном дверей, коридоров и развилок. Твоя цель — найти комнату с сокровищем. У тебя с собой блокнот и карандаш, но нет карты.

Каждый раз, когда ты доходишь до развилки, ты записываешь в блокнот:
"Я сейчас в коридоре A, и уже пошёл в дверь 1 из 3 возможных."

Если за этой дверью тупик — ты возвращаешься назад, смотришь в блокнот и говоришь:
"Хм, я был в коридоре A и пробовал дверь 1. Попробую теперь дверь 2."

Идёшь туда, снова записываешь шаг, и так далее.

Так и работает Backtracking в программировании:
ты пробуешь решение
если оно не подходит — возвращаешься назад, отменяешь выбор и пробуешь другое
ты не забываешь, где был, и всегда можешь шагнуть обратно, чтобы попробовать что-то другое

#backtracking
Please open Telegram to view this post
VIEW IN TELEGRAM
1
➡️Также уточнение

Стартуем сразу с 🟡medium задач, так как это довольно сложная тема и задач уровня 🟢easy для нее нет
Please open Telegram to view this post
VIEW IN TELEGRAM
🟡Medium
2698. Find the Punishment Number of an Integer

Company: 🔍📱📕

📝Дано число n, верните номер наказания.

Номер наказания для n определяется, как сумма квадратов всех целых чисел i, таких, что:

1 <= i <= n
десятичное представление i * i можно разбить таким образом, что сумма частей разбиения будет равна i

💡: пройди все числа от 1 до n и для каждого перебери все способы разрезать число по цифрам, возвращаясь назад, если их сумма превышает нужное значение

#leetcode2698 | #medium #backtracking
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 2698

Time: O(n * 2^k)
Space: O(k), [k = O(log^2 n)]

💡 Идея
🟦перебираем все числа от 1 до n и для каждого вычисляем его квадрат, а затем вызываем вспомогательный метод canPartition, чтобы проверить условие разложения

🟦если условие выполняется — т.е. квадрат можно разбить на части, сумма которых равна самому числу — то этот квадрат прибавляется к сумме res

🟦метод canPartition реализует backtracking, пытаясь проверить все возможные комбинации подстрок, преобразуемых в числа, и проверить, можно ли их суммой получить исходное число:
на каждом шаге выбираем очередную подстроку, уменьшаем целевое значение target на её числовое значение и делаем рекурсивный вызов для оставшейся строки

если сумма не совпадает или превышает целевое значение, происходит откат (backtrack) и пробуется следующий вариант разбиения

👩‍💻 Java Algo | #solution2698
Please open Telegram to view this post
VIEW IN TELEGRAM
🟡Medium
1079. Letter Tile Possibilities

Company: 🏢📱📱

📝Дана строка tiles, состоящая только из заглавных букв.

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

💡: рекурсивно составляйте все возможные комбинации, используя массив частот символов

#leetcode1079 | #medium #backtracking
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 1079

Time: O(n!)
Space: O(n)

💡 Идея
🟦
Представьте, что мы играем с фишками «Скрабла» и у нас есть строка «AAABBC».

Здесь можно сделать важное замечание: на самом деле важно не расположение каждой буквы, а количество имеющихся в наличии фишек каждой буквы. Независимо от того, используем ли мы первую «А» или вторую «А», последовательности, которые мы можем создать, не меняются — нам просто нужно знать, что у нас есть три «А».

Это понимание подводит нас к ключевому решению: вместо отслеживания отдельных букв мы можем отслеживать частоту каждой из них

🟦Сначала создадим массив freq длиной 26, где каждый элемент соответствует количеству вхождений соответствующей буквы в строке, что позволит эффективно отслеживать, какие символы ещё можно использовать при построении комбинаций

🟦Затем используем рекурсивную функцию backtrack, которая перебирает все возможные варианты построения комбинаций:
на каждой итерации выбираем букву, которая ещё осталась

уменьшаем её частоту и добавляем 1 к результату, что означает новую уникальную комбинацию

вызываем рекурсивно backtrack, чтобы продолжить построение более длинных комбинаций

затем восстанавливаем частоту буквы обратно (backtracking)

🟦Таким образом, каждая ветка рекурсии учитывает все возможные перестановки символов с текущим набором оставшихся, тем самым эффективно находя общее число уникальных комбинаций всех возможных длин

👩‍💻 Java Algo | #solution1079
Please open Telegram to view this post
VIEW IN TELEGRAM
🟡Medium
47. Permutations II

Company: 📱📱🅰️

📝Дан целочисленный массив, который может содержать дубликаты. Верните все возможные уникальные перестановки в любом порядке

💡: отсортируйте массив и пропускайте одинаковые элементы на одном уровне рекурсии, чтобы избежать дубликатов в перестановках

#leetcode47 | #medium #backtracking
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 47

Time: O(n*n!)
Space: O(n!)

💡 Идея
🟦Сначала отсортируем массив, чтобы одинаковые числа оказались рядом — это необходимо для последующей фильтрации повторяющихся перестановок

🟦Далее используем ключевой метод backtrack:
внутри цикла перебираем все возможные числа, которые ещё не были использованы

после добавления числа в текущую комбинацию и отметки его как использованного рекурсивно вызываем backtrack

после возврата из рекурсии — делаем откат (backtrack): число удаляется и помечается как неиспользованное

при этом, если текущий элемент равен предыдущему, но предыдущий ещё не был использован в текущей ветке построения, значит, мы уже рассматривали эту комбинацию на этом уровне рекурсии и её нужно пропустить, чтобы избежать дубликатов в результате

когда текущая перестановка достигает нужной длины (размер входного массива), она добавляется в итоговый список

🟦Такой подход гарантирует, что будут перебраны все возможные уникальные перестановки без дубликатов, и результат будет полным и корректным

👩‍💻 Java Algo | #solution47
Please open Telegram to view this post
VIEW IN TELEGRAM
🟡Medium
306. Additive Number

Company: 📱

📝Дана строка, содержащая только цифры, вернуть true, если она является аддитивным числом.

Аддитивное число — это строка, цифры которой могут образовывать допустимую аддитивную последовательность:

содержит не менее трёх чисел
каждое последующее число в последовательности должно быть суммой двух предыдущих (за исключением первых двух)
числа в последовательности не могут иметь начальных нулей

💡: переберите все возможные комбинации первых двух чисел и продолжайте разбиение строки, если следующее число равно их сумме

#leetcode306 | #medium #backtracking
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 306

Time: O(2^n)
Space: O(n)

💡 Идея
🟦Из основного метода вызываем вспомогательный рекурсивный метод backtrack, который принимает:
исходную строку с цифрами (num)
текущую позицию в строке (start)
два предыдущих числа (n1, n2)
количество найденных чисел в последовательности (count)

🟦В методе backtrack делаем следующее:
на каждой итерации формируем текущее число currNum, последовательно добавляя цифры из строки

если два предыдущих числа равны -1 (ещё не заданы), или сумма двух предыдущих равна текущему числу, рекурсивно проверяем продолжение цепочки с новым числом

условие завершения — если достигнут конец строки и найдено хотя бы три числа

также учитываем случаи, когда число начинается с нуля и его длина больше одного, прекращая обработку этой ветки

🟦Таким образом, мы перебираем все возможные варианты составления текущего числа, чтобы оно соответствовало условиям аддитивной последовательности — либо как одно из первых двух чисел, либо как сумма двух предыдущих, проверяя строку до самого конца

👩‍💻 Java Algo | #solution306
Please open Telegram to view this post
VIEW IN TELEGRAM
2
🟡Medium
1415. The k-th Lexicographical String of All Happy Strings of Length n

Company: 🔍📱🏢

📝Даны два целых числа n и k. Рассмотрите отсортированный в лексикографическом порядке список всех счастливых строк длины n.

Верните k-ю строку этого списка или пустую строку, если количество счастливых строк меньше.

Счастливая строка — это строка, которая:
состоит только из букв набора ['a', 'b', 'c']
не содержит двух рядом стоящих одинаковых символов

Список счастливых строк для примера 3:
["aba", "abc", "aca", "acb", "bab", "bac", "bca", "bcb", "cab", "cac", "cba", "cbc"]


💡: рекурсивно стройте строки, добавляя буквы от 'a' к 'c', избегая одинаковых соседних символов

#leetcode1415 | #medium #backtracking
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 1415

Time: O(2^n)
Space: O(n*2^n)

💡 Идея
🟦Решение состоит в том, чтобы строить последовательности, всегда выбирая наименьшую возможную букву в лексикографическом порядке, при этом избегая повторов подряд. Для этого в методе backtrack:

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

если условие выполнено, добавляем букву и рекурсивно вызываем backtrack, чтобы продолжить построение

когда длина текущей строки достигает заданного n, она считается готовой и добавляется в список all. Этот список автоматически формируется в лексикографическом порядке, так как перебор букв идёт от 'a' к 'c'

после возврата из рекурсии удаляем последнюю добавленную букву, чтобы освободить место для других вариантов

🟦В конце, когда все варианты построены, остаётся просто вернуть k-ю строку из списка или пустую строку, если k превышает количество сгенерированных последовательностей

👩‍💻 Java Algo | #solution1415
Please open Telegram to view this post
VIEW IN TELEGRAM
2
🔴Hard
51. N-Queens

Company: 🔍📕📱

📝Дано целое число n, найдите все различные решения головоломки с n ферзями.

Задача об n ферзях — это расстановка n ферзей на n x n шахматной доске таким образом, чтобы никакие два ферзя не атаковали друг друга.

Каждое решение должно содержать отдельную конфигурацию доски с размещением n ферзей, где 'Q' и '.' обозначают ферзя и пустое место соответственно

💡: используйте backtracking, ставя ферзя построчно и одновременно отслеживая занятые столбцы и диагонали

#leetcode51 | #hard #backtracking
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 51

Time: O(n!)
Space: O(n)

💡 Идея
🟦Важно заметить, какие позиции ограничивает каждый новый ферзь. Например, поставив одного ферзя в клетку, можно точно сказать, что в текущие столбец и строку второго ферзя уже не поставить. Остается только учесть диагонали, но как это сделать?

🟦Введем идею с уникальными идентификаторами диагоналей:
Для положительной диагонали (направлена вверх, если начинать проводить слева) идентификатором служит сумма индексов строки и столбца
Для отрицательной диагонали (направлена вниз) — разница строки и столбца
Таким образом, при добавлении ферзя мы фиксируем не только его столбец, но и обе диагонали, блокируя тем самым возможность поставить туда других

🟦Получаем следующий алгоритм:
Для каждой клетки текущей строки проверяем возможность постановки ферзя
Если позиция допустима, добавляем её в решение и рекурсивно переходим к следующей строке
После возврата из рекурсии убираем сохранённую позицию, чтобы продолжить перебор
Когда доходим до последней строки и удаётся расставить всех n ферзей, преобразуем текущее состояние доски в список строк и добавляем его в итоговый результат

👩‍💻 Java Algo | #solution51
Please open Telegram to view this post
VIEW IN TELEGRAM
1
🔴Hard
679. 24 Game

Company: 🔍🚖📱

📝Дан массив целых чисел cards длиной 4, где каждая карта содержит число от 1 до 9.

Вам нужно составить из чисел на этих карточках математическое выражение, используя операторы ['+', '-', '*', '/'] и скобки (), чтобы получить значение 24.

При этом действуют следующие правила:

Оператор деления '/ 'представляет собой действительное деление, а не целочисленное
Например, 4 / (1 - 2 / 3) = 4 / (1 / 3) = 12

Каждая операция применяется только между двумя числами (унарные минусы запрещены)
Числа нельзя объединять
Например, если cards = [1, 2, 1, 2], то выражение "12 + 12" недопустимо


Верните true, если возможно получить выражение, равное 24

💡: попробуйте перебрать все пары чисел и заменить их результатом арифметической операции, рекурсивно сводя задачу к одному числу

#leetcode679 | #hard #backtracking
Please open Telegram to view this post
VIEW IN TELEGRAM
Решение задачи 679

Time: O(n³ * 3^n * n!)
Space: O(n²)

💡 Идея
🟦Переводим исходный массив в список вещественных чисел для удобной работы. Затем запускаем рекурсивный метод backtrack, передавая в него этот список

🟦В методе просто перебираем все пары чисел в текущем списке и плюсом для каждой перебираем все возможные арифметические комбинации

🟦Добавляем в новый список результат комбинации и оставшиеся в старом списке числа, а затем рекурсивно вызываем backtrack для проверки текущего варианта

🟦После возврата из рекурсии, удаляем последнюю добавленную комбинацию, используя принцип backtracking для перебора всех возможных вариантов

🟦Базовым случаем является проверка на размер списка:
если в списке остался только один элемент, проверяется, близок ли он к 24 с погрешностью 0.1, чтобы учитывать неточности вычислений с плавающей запятой
если чисел больше одного, действуем по описанному алгоритму

👩‍💻 Java Algo | #solution679
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
🔴Hard
37. Sudoku Solver

Company: 🔍📕📱

📝Напишите алгоритм, который решает головоломку Судоку, заполняя все пустые клетки.

Игровое поле представлено в виде двумерного массива символов, где каждая клетка содержит либо цифру '1'–'9', либо символ '.', обозначающий пустую клетку.

Условия решения:
В каждой строке — все цифры 1–9 без повторов
В каждом столбце — все цифры 1–9 без повторов
В каждом блоке 3×3 — все цифры 1–9 без повторов

💡: при размещении числа, сразу исключайте его из строки, столбца и блока, чтобы сократить поиск

#leetcode37 | #hard #backtracking
Please open Telegram to view this post
VIEW IN TELEGRAM