Задача: 751. IP to CIDR
Сложность: medium
Дан указатель на начало односвязного списка и два целых числа left и right, где left <= right. Необходимо перевернуть узлы списка, начиная с позиции left и заканчивая позицией right, и вернуть измененный список.
Пример:
👨💻 Алгоритм:
1⃣ Преобразовать начальный IP-адрес в целое число.
2⃣ Пока количество оставшихся IP-адресов n больше нуля: Определить наибольший блок, который начинается с текущего IP-адреса и не превышает количество оставшихся IP-адресов. Добавить этот блок к результату. Увеличить текущий IP-адрес на размер блока. Уменьшить количество оставшихся IP-адресов n.
3⃣ Преобразовать блоки обратно в формат CIDR и вернуть их.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан указатель на начало односвязного списка и два целых числа left и right, где left <= right. Необходимо перевернуть узлы списка, начиная с позиции left и заканчивая позицией right, и вернуть измененный список.
Пример:
Input: ip = "255.0.0.7", n = 10
Output: ["255.0.0.7/32","255.0.0.8/29","255.0.0.16/32"]
fun ipToInt(ip: String): Int {
val parts = ip.split(".").map { it.toInt() }
return (parts[0] shl 24) + (parts[1] shl 16) + (parts[2] shl 8) + parts[3]
}
fun intToIp(num: Int): String {
return "${(num shr 24) and 255}.${(num shr 16) and 255}.${(num shr 8) and 255}.${num and 255}"
}
fun cidr(ip: String, prefixLength: Int): String {
return "$ip/$prefixLength"
}
fun findCidrBlocks(startIp: String, n: Int): List<String> {
var start = ipToInt(startIp)
val result = mutableListOf<String>()
var remaining = n
while (remaining > 0) {
var maxSize = 1
while (maxSize <= start && maxSize <= remaining) {
maxSize = maxSize shl 1
}
maxSize = maxSize shr 1
while (start % maxSize != 0) {
maxSize = maxSize shr 1
}
result.add(cidr(intToIp(start), 32 - Integer.bitCount(maxSize - 1) + 1))
start += maxSize
remaining -= maxSize
}
return result
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1539. Kth Missing Positive Number
Сложность: easy
Дан массив
Верните k-й положительный целочисленный элемент, который отсутствует в этом массиве.
Пример:
👨💻 Алгоритм:
1⃣ Проверьте, является ли k-й отсутствующий номер меньше первого элемента массива. Если это так, верните k. Уменьшите k на количество положительных чисел, отсутствующих до начала массива: k -= arr[0] - 1.
2⃣ Итерируйтесь по элементам массива. На каждом шаге вычисляйте количество отсутствующих положительных чисел между i+1-м и i-м элементами: currMissing = arr[i + 1] - arr[i] - 1. Сравните k с currMissing. Если k <= currMissing, то число для возврата находится между arr[i + 1] и arr[i], и вы можете его вернуть: arr[i] + k. В противном случае уменьшите k на currMissing и продолжайте.
3⃣ Если элемент, который нужно вернуть, больше последнего элемента массива, верните его: arr[n - 1] + k.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан массив
arr из положительных целых чисел, отсортированных в строго возрастающем порядке, и целое число k.Верните k-й положительный целочисленный элемент, который отсутствует в этом массиве.
Пример:
Input: arr = [2,3,4,7,11], k = 5
Output: 9
Explanation: The missing positive integers are [1,5,6,8,9,10,12,13,...]. The 5th missing positive integer is 9.
class Solution {
fun findKthPositive(arr: IntArray, k: Int): Int {
var k = k
if (k <= arr[0] - 1) {
return k
}
k -= arr[0] - 1
val n = arr.size
for (i in 0 until n - 1) {
val currMissing = arr[i + 1] - arr[i] - 1
if (k <= currMissing) {
return arr[i] + k
}
k -= currMissing
}
return arr[n - 1] + k
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 852. Peak Index in a Mountain Array
Сложность: medium
Вам дан целочисленный массив горы arr длины n, где значения увеличиваются до пикового элемента, а затем уменьшаются.
Верните индекс пикового элемента.
Ваша задача — решить это с временной сложностью O(log(n)).
Пример:
👨💻 Алгоритм:
1⃣ Создайте целочисленную переменную i и инициализируйте её значением 0.
2⃣ Используя цикл while, проверьте, если текущий элемент, на который указывает i, меньше следующего элемента на индексе i + 1. Если arr[i] < arr[i + 1], увеличьте i на 1.
3⃣ В противном случае, если arr[i] > arr[i + 1], верните i.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан целочисленный массив горы arr длины n, где значения увеличиваются до пикового элемента, а затем уменьшаются.
Верните индекс пикового элемента.
Ваша задача — решить это с временной сложностью O(log(n)).
Пример:
Input: arr = [0,1,0]
Output: 1
class Solution {
fun peakIndexInMountainArray(arr: IntArray): Int {
var i = 0
while (arr[i] < arr[i + 1]) {
i++
}
return i
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1135. Connecting Cities With Minimum Cost
Сложность: medium
Есть n городов, пронумерованных от 1 до n. Вам даны целое число n и массив connections, где connections[i] = [xi, yi, costi] указывает, что стоимость соединения города xi и города yi (двунаправленное соединение) равна costi.
Верните минимальную стоимость для соединения всех n городов так, чтобы между каждой парой городов был хотя бы один путь. Если невозможно соединить все n городов, верните -1.
Стоимость - это сумма использованных стоимостей соединений.
Пример:
👨💻 Алгоритм:
1⃣ Сортировка рёбер:
Отсортируйте все соединения (рёбра) в графе по их весам (стоимости) в порядке возрастания.
2⃣ Итерация по рёбрам и объединение:
Используйте структуру данных Disjoint Set (Union-Find) для проверки циклов и объединения поддеревьев. Для каждого ребра проверьте, принадлежат ли его концы разным поддеревьям, и если да, объедините их, добавив ребро в минимальное остовное дерево (MST).
3⃣ Проверка соединённости:
Подсчитайте количество рёбер в MST. Если оно меньше n-1, верните -1, так как соединить все города невозможно. Иначе верните суммарную стоимость рёбер в MST.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Есть n городов, пронумерованных от 1 до n. Вам даны целое число n и массив connections, где connections[i] = [xi, yi, costi] указывает, что стоимость соединения города xi и города yi (двунаправленное соединение) равна costi.
Верните минимальную стоимость для соединения всех n городов так, чтобы между каждой парой городов был хотя бы один путь. Если невозможно соединить все n городов, верните -1.
Стоимость - это сумма использованных стоимостей соединений.
Пример:
Input: n = 3, connections = [[1,2,5],[1,3,6],[2,3,1]]
Output: 6
Explanation: Choosing any 2 edges will connect all cities so we choose the minimum 2.
Отсортируйте все соединения (рёбра) в графе по их весам (стоимости) в порядке возрастания.
Используйте структуру данных Disjoint Set (Union-Find) для проверки циклов и объединения поддеревьев. Для каждого ребра проверьте, принадлежат ли его концы разным поддеревьям, и если да, объедините их, добавив ребро в минимальное остовное дерево (MST).
Подсчитайте количество рёбер в MST. Если оно меньше n-1, верните -1, так как соединить все города невозможно. Иначе верните суммарную стоимость рёбер в MST.
class DisjointSet(n: Int) {
private val parent = IntArray(n + 1) { it }
fun find(x: Int): Int {
if (parent[x] != x) {
parent[x] = find(parent[x])
}
return parent[x]
}
fun union(x: Int, y: Int) {
val rootX = find(x)
val rootY = find(y)
if (rootX != rootY) {
parent[rootY] = rootX
}
}
}
class Solution {
fun minimumCost(n: Int, connections: Array<IntArray>): Int {
connections.sortBy { it[2] }
val disjointSet = DisjointSet(n)
var totalCost = 0
var edgesUsed = 0
for (connection in connections) {
val (x, y, cost) = connection
if (disjointSet.find(x) != disjointSet.find(y)) {
disjointSet.union(x, y)
totalCost += cost
edgesUsed += 1
if (edgesUsed == n - 1) {
return totalCost
}
}
}
return if (edgesUsed == n - 1) totalCost else -1
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 395. Longest Substring with At Least K Repeating Characters
Сложность: medium
Дана строка s и целое число k, верните длину самой длинной подстроки строки s, такая что частота каждого символа в этой подстроке больше или равна k.
Если такой подстроки не существует, верните 0.
Пример:
👨💻 Алгоритм:
1⃣ Генерируйте подстроки из строки s, начиная с индекса start и заканчивая индексом end. Используйте массив countMap для хранения частоты каждого символа в подстроке.
2⃣ Метод isValid использует countMap для проверки, что каждый символ в подстроке встречается как минимум k раз. Если условие выполняется, текущая подстрока считается допустимой.
3⃣ Отслеживайте максимальную длину допустимой подстроки, обновляя её, когда найдена более длинная подстрока, удовлетворяющая условиям. В конце возвращайте длину самой длинной подстроки.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дана строка s и целое число k, верните длину самой длинной подстроки строки s, такая что частота каждого символа в этой подстроке больше или равна k.
Если такой подстроки не существует, верните 0.
Пример:
Input: s = "aaabb", k = 3
Output: 3
Explanation: The longest substring is "aaa", as 'a' is repeated 3 times.
class Solution {
fun longestSubstring(s: String, k: Int): Int {
if (s.isEmpty() || k > s.length) {
return 0
}
val n = s.length
var result = 0
for (start in 0 until n) {
val countMap = IntArray(26)
for (end in start until n) {
countMap[s[end] - 'a']++
if (isValid(countMap, k)) {
result = maxOf(result, end - start + 1)
}
}
}
return result
}
private fun isValid(countMap: IntArray, k: Int): Boolean {
var countLetters = 0
var countAtLeastK = 0
for (count in countMap) {
if (count > 0) countLetters++
if (count >= k) countAtLeastK++
}
return countLetters == countAtLeastK
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1238. Circular Permutation in Binary Representation
Сложность: medium
Вам дан массив строк arr. Строка s образуется конкатенацией подпоследовательности arr, содержащей уникальные символы. Верните максимально возможную длину s. Подпоследовательность - это массив, который может быть получен из другого массива путем удаления некоторых или ни одного элемента без изменения порядка оставшихся элементов.
Пример:
👨💻 Алгоритм:
1⃣ Использование рекурсивного подхода:
Для каждой строки в массиве arr проверяем, можем ли мы добавить ее к текущей комбинации уникальных символов.
Если можем, добавляем ее и продолжаем рекурсивный вызов для следующей строки.
Если не можем, пропускаем текущую строку и переходим к следующей.
2⃣ Проверка уникальности символов:
Для проверки уникальности символов используем множество (set). Если все символы строки уникальны и не пересекаются с символами текущей комбинации, мы можем добавить строку.
3⃣ Поиск максимальной длины:
На каждом шаге обновляем максимальную длину, если текущая комбинация уникальных символов длиннее предыдущей максимальной длины.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан массив строк arr. Строка s образуется конкатенацией подпоследовательности arr, содержащей уникальные символы. Верните максимально возможную длину s. Подпоследовательность - это массив, который может быть получен из другого массива путем удаления некоторых или ни одного элемента без изменения порядка оставшихся элементов.
Пример:
Input: arr = ["un","iq","ue"]
Output: 4
Для каждой строки в массиве arr проверяем, можем ли мы добавить ее к текущей комбинации уникальных символов.
Если можем, добавляем ее и продолжаем рекурсивный вызов для следующей строки.
Если не можем, пропускаем текущую строку и переходим к следующей.
Для проверки уникальности символов используем множество (set). Если все символы строки уникальны и не пересекаются с символами текущей комбинации, мы можем добавить строку.
На каждом шаге обновляем максимальную длину, если текущая комбинация уникальных символов длиннее предыдущей максимальной длины.
class Solution {
fun maxLength(arr: List<String>): Int {
fun isUnique(s: String): Boolean {
return s.toSet().size == s.length
}
fun backtrack(index: Int, current: String): Int {
if (!isUnique(current)) return 0
var maxLength = current.length
for (i in index until arr.size) {
maxLength = maxOf(maxLength, backtrack(i + 1, current + arr[i]))
}
return maxLength
}
return backtrack(0, "")
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 515. Find Largest Value in Each Tree Row
Сложность: medium
Дан корень двоичного дерева, верните массив наибольших значений в каждой строке дерева (индексация с 0).
Пример:
👨💻 Алгоритм:
1⃣ Если корень дерева равен null (пустое дерево), верните пустой список. Инициализируйте список ans для хранения результатов и очередь с корнем дерева для выполнения поиска в ширину (BFS).
2⃣ Выполните BFS, пока очередь не пуста: инициализируйте currMax минимальным значением и сохраните длину очереди в currentLength. Повторите currentLength раз: удалите узел из очереди, обновите currMax, если значение узла больше. Для каждого дочернего узла, если он не равен null, добавьте его в очередь.
3⃣ Добавьте currMax в ans. Верните ans.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан корень двоичного дерева, верните массив наибольших значений в каждой строке дерева (индексация с 0).
Пример:
Input: root = [1,3,2,5,3,null,9]
Output: [1,3,9]
class Solution {
fun largestValues(root: TreeNode?): List<Int> {
if (root == null) return emptyList()
val ans = mutableListOf<Int>()
val queue = ArrayDeque<TreeNode>()
queue.add(root)
while (queue.isNotEmpty()) {
val currentLength = queue.size
var currMax = Int.MIN_VALUE
repeat(currentLength) {
val node = queue.removeFirst()
currMax = maxOf(currMax, node.`val`)
node.left?.let { queue.add(it) }
node.right?.let { queue.add(it) }
}
ans.add(currMax)
}
return ans
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1041. Robot Bounded In Circle
Сложность: medium
На бесконечной плоскости робот изначально стоит в точке (0, 0) и обращен лицом на север. Обратите внимание, что: северное направление - это положительное направление оси y. южное направление - это отрицательное направление оси y. восточное направление - это положительное направление оси x. западное направление - это отрицательное направление оси x. робот может получить одну из трех команд: "G": идти прямо 1 единицу. "L": повернуть на 90 градусов влево (т.е, "R": повернуть на 90 градусов вправо (т. е. по часовой стрелке). Робот выполняет данные инструкции по порядку и повторяет их до бесконечности. Возвращается true тогда и только тогда, когда в плоскости существует окружность, такая, что робот никогда не покидает ее.
Пример:
👨💻 Алгоритм:
1⃣ Понимание поведения робота:
Мы анализируем, как робот движется в пределах одной серии команд. Если он вернется в начальную точку или изменит направление после выполнения всех команд, значит, он будет двигаться по замкнутой траектории, что соответствует условию задачи.
2⃣ Изменение направления:
Робот может двигаться на север (0), восток (1), юг (2), или запад (3). Эти направления можно моделировать с помощью векторов (dx, dy): север (0, 1), восток (1, 0), юг (0, -1), запад (-1, 0).
3⃣ Обработка команд:
Пройдите по всем командам и обновите позицию робота и направление, в котором он движется.
Проверка состояния робота:
После выполнения всех команд проверьте, вернулся ли робот в начальную точку (0, 0) или изменил направление. Если одно из этих условий выполнено, робот будет двигаться по замкнутой траектории.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
На бесконечной плоскости робот изначально стоит в точке (0, 0) и обращен лицом на север. Обратите внимание, что: северное направление - это положительное направление оси y. южное направление - это отрицательное направление оси y. восточное направление - это положительное направление оси x. западное направление - это отрицательное направление оси x. робот может получить одну из трех команд: "G": идти прямо 1 единицу. "L": повернуть на 90 градусов влево (т.е, "R": повернуть на 90 градусов вправо (т. е. по часовой стрелке). Робот выполняет данные инструкции по порядку и повторяет их до бесконечности. Возвращается true тогда и только тогда, когда в плоскости существует окружность, такая, что робот никогда не покидает ее.
Пример:
Input: instructions = "GGLLGG"
Output: true
Мы анализируем, как робот движется в пределах одной серии команд. Если он вернется в начальную точку или изменит направление после выполнения всех команд, значит, он будет двигаться по замкнутой траектории, что соответствует условию задачи.
Робот может двигаться на север (0), восток (1), юг (2), или запад (3). Эти направления можно моделировать с помощью векторов (dx, dy): север (0, 1), восток (1, 0), юг (0, -1), запад (-1, 0).
Пройдите по всем командам и обновите позицию робота и направление, в котором он движется.
Проверка состояния робота:
После выполнения всех команд проверьте, вернулся ли робот в начальную точку (0, 0) или изменил направление. Если одно из этих условий выполнено, робот будет двигаться по замкнутой траектории.
class Solution {
fun isRobotBounded(instructions: String): Boolean {
val directions = arrayOf(Pair(0, 1), Pair(1, 0), Pair(0, -1), Pair(-1, 0))
var x = 0
var y = 0
var direction = 0
for (instruction in instructions) {
when (instruction) {
'G' -> {
x += directions[direction].first
y += directions[direction].second
}
'L' -> direction = (direction + 3) % 4
'R' -> direction = (direction + 1) % 4
}
}
return (x == 0 && y == 0) || direction != 0
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1228. Missing Number In Arithmetic Progression
Сложность: easy
В массиве arr значения находились в арифметической прогрессии: значения arr[i + 1] - arr[i] равны для всех 0 <= i < arr.length - 1.
Из массива arr было удалено значение, которое не было первым или последним значением в массиве.
Дан массив arr, вернуть удаленное значение.
Пример:
👨💻 Алгоритм:
1⃣ Рассчитать разность difference между элементами арифметической прогрессии.
2⃣ Начать с первого элемента массива и последовательно увеличивать ожидаемое значение на difference, проверяя каждый элемент массива.
3⃣ Вернуть первое ожидаемое значение, которое не совпадает с текущим значением в массиве.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
В массиве arr значения находились в арифметической прогрессии: значения arr[i + 1] - arr[i] равны для всех 0 <= i < arr.length - 1.
Из массива arr было удалено значение, которое не было первым или последним значением в массиве.
Дан массив arr, вернуть удаленное значение.
Пример:
Input: arr = [5,7,11,13]
Output: 9
Explanation: The previous array was [5,7,9,11,13].
class Solution {
fun missingNumber(arr: IntArray): Int {
val n = arr.size
val difference = (arr[n - 1] - arr[0]) / n
var expected = arr[0]
for (val in arr) {
if (val != expected) {
return expected
}
expected += difference
}
return expected
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 494. Target Sum
Сложность: medium
Вам дан массив целых чисел nums и целое число target.
Вы хотите создать выражение из nums, добавляя один из символов '+' или '-' перед каждым числом в nums, а затем объединяя все числа.
Например, если nums = [2, 1], вы можете добавить '+' перед 2 и '-' перед 1, а затем объединить их, чтобы получить выражение "+2-1".
Верните количество различных выражений, которые можно построить и которые оцениваются в target.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и вызов рекурсивной функции
Создайте переменную для хранения количества решений (count). Вызовите рекурсивную функцию calculate с начальными параметрами (nums, начальный индекс 0, начальная сумма 0, и target).
2⃣ Рекурсивная функция calculate
Если текущий индекс равен длине массива, проверьте, равна ли текущая сумма значению target. Если да, увеличьте счетчик решений. В противном случае, вызовите функцию рекурсивно дважды: добавляя и вычитая текущее значение из суммы.
3⃣ Возврат результата
После завершения всех рекурсивных вызовов верните значение счетчика решений.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан массив целых чисел nums и целое число target.
Вы хотите создать выражение из nums, добавляя один из символов '+' или '-' перед каждым числом в nums, а затем объединяя все числа.
Например, если nums = [2, 1], вы можете добавить '+' перед 2 и '-' перед 1, а затем объединить их, чтобы получить выражение "+2-1".
Верните количество различных выражений, которые можно построить и которые оцениваются в target.
Пример:
Input: nums = [1,1,1,1,1], target = 3
Output: 5
Explanation: There are 5 ways to assign symbols to make the sum of nums be target 3.
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3
Создайте переменную для хранения количества решений (count). Вызовите рекурсивную функцию calculate с начальными параметрами (nums, начальный индекс 0, начальная сумма 0, и target).
Если текущий индекс равен длине массива, проверьте, равна ли текущая сумма значению target. Если да, увеличьте счетчик решений. В противном случае, вызовите функцию рекурсивно дважды: добавляя и вычитая текущее значение из суммы.
После завершения всех рекурсивных вызовов верните значение счетчика решений.
class Solution {
var count = 0
fun findTargetSumWays(nums: IntArray, S: Int): Int {
calculate(nums, 0, 0, S)
return count
}
fun calculate(nums: IntArray, i: Int, sum: Int, S: Int) {
if (i == nums.size) {
if (sum == S) {
count++
}
} else {
calculate(nums, i + 1, sum + nums[i], S)
calculate(nums, i + 1, sum - nums[i], S)
}
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 247. Strobogrammatic Number II
Сложность: medium
Дано целое число n, верните все стробограмматические числа длины n. Ответ можно возвращать в любом порядке.
Стробограмматическое число — это число, которое выглядит одинаково при повороте на 180 градусов (если посмотреть вверх ногами).
Пример:
👨💻 Алгоритм:
1⃣ Задаём пару «переворачиваемых» цифр:
("0","0"), ("1","1"), ("6","9"), ("8","8"), ("9","6").
2⃣ Используем рекурсию для расчета длины всех комбинаций n, начиная с базовых случаев
n == 0→[""]
n == 1→["0", "1", "8"]
3⃣ Для каждой строки generate(n - 2)вставляйте пару символов по краям.
Не добавляйте '0'в начало, если это внешний уровень ( n == finalLength).
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дано целое число n, верните все стробограмматические числа длины n. Ответ можно возвращать в любом порядке.
Стробограмматическое число — это число, которое выглядит одинаково при повороте на 180 градусов (если посмотреть вверх ногами).
Пример:
Input: n = 2
Output: ["11","69","88","96"]
("0","0"), ("1","1"), ("6","9"), ("8","8"), ("9","6").
n == 0→[""]
n == 1→["0", "1", "8"]
Не добавляйте '0'в начало, если это внешний уровень ( n == finalLength).
class Solution {
private val reversiblePairs = listOf(
listOf('0', '0'), listOf('1', '1'),
listOf('6', '9'), listOf('8', '8'), listOf('9', '6')
)
private fun generateStroboNumbers(n: Int, finalLength: Int): List<String> {
if (n == 0) {
return listOf("")
}
if (n == 1) {
return listOf("0", "1", "8")
}
val prevStroboNums = generateStroboNumbers(n - 2, finalLength)
val currStroboNums = mutableListOf<String>()
for (prevStroboNum in prevStroboNums) {
for (pair in reversiblePairs) {
if (pair[0] != '0' || n != finalLength) {
currStroboNums.add("${pair[0]}$prevStroboNum${pair[1]}")
}
}
}
return currStroboNums
}
fun findStrobogrammatic(n: Int): List<String> {
return generateStroboNumbers(n, n)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit
Сложность: medium
Дан массив целых чисел nums и целое число limit. Вернуть размер самой длинной непустой подстроки, такая что абсолютная разница между любыми двумя элементами этой подстроки меньше или равна limit.
Пример:
👨💻 Алгоритм:
1⃣ Инициализировать два дека (minDeque и maxDeque) для хранения минимальных и максимальных значений в текущем окне и переменную left для начала окна.
2⃣ Итеративно добавлять элементы в дек, поддерживая условие абсолютной разницы между максимальным и минимальным элементом в окне, чтобы она была не больше limit, при необходимости сдвигая left.
3⃣ Обновлять maxLength, проверяя максимальную длину текущего окна, и возвращать maxLength как результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив целых чисел nums и целое число limit. Вернуть размер самой длинной непустой подстроки, такая что абсолютная разница между любыми двумя элементами этой подстроки меньше или равна limit.
Пример:
Input: nums = [8,2,4,7], limit = 4
Output: 2
Explanation: All subarrays are:
[8] with maximum absolute diff |8-8| = 0 <= 4.
[8,2] with maximum absolute diff |8-2| = 6 > 4.
[8,2,4] with maximum absolute diff |8-2| = 6 > 4.
[8,2,4,7] with maximum absolute diff |8-2| = 6 > 4.
[2] with maximum absolute diff |2-2| = 0 <= 4.
[2,4] with maximum absolute diff |2-4| = 2 <= 4.
[2,4,7] with maximum absolute diff |2-7| = 5 > 4.
[4] with maximum absolute diff |4-4| = 0 <= 4.
[4,7] with maximum absolute diff |4-7| = 3 <= 4.
[7] with maximum absolute diff |7-7| = 0 <= 4.
Therefore, the size of the longest subarray is 2.
import java.util.PriorityQueue
class Solution {
fun longestSubarray(nums: IntArray, limit: Int): Int {
val maxHeap = PriorityQueue<IntArray> { a, b -> b[0] - a[0] }
val minHeap = PriorityQueue<IntArray>(compareBy { it[0] })
var left = 0
var maxLength = 0
for (right in nums.indices) {
maxHeap.offer(intArrayOf(nums[right], right))
minHeap.offer(intArrayOf(nums[right], right))
while (maxHeap.peek()[0] - minHeap.peek()[0] > limit) {
left = minOf(maxHeap.peek()[1], minHeap.peek()[1]) + 1
while (maxHeap.peek()[1] < left) maxHeap.poll()
while (minHeap.peek()[1] < left) minHeap.poll()
}
maxLength = maxOf(maxLength, right - left + 1)
}
return maxLength
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 56. Merge Intervals
Сложность: medium
Дан массив интервалов, где intervals[i] = [starti, endi]. Объедините все перекрывающиеся интервалы и верните массив неперекрывающихся интервалов, которые покрывают все интервалы во входных данных.
Пример:
👨💻 Алгоритм:
1⃣ Представление графа:
Имея представленную интуицию, мы можем изобразить граф в виде списка смежности, вставляя направленные ребра в обоих направлениях, чтобы симулировать неориентированные ребра.
2⃣ Определение компонент связности:
Для определения, в какой компоненте связности находится каждый узел, мы выполняем обходы графа от произвольных непосещенных узлов до тех пор, пока все узлы не будут посещены. Для эффективности мы храним посещенные узлы в множестве (Set), что позволяет проводить проверки на принадлежность и вставку за константное время.
3⃣ Объединение интервалов внутри компонент:
Наконец, мы рассматриваем каждую связную компоненту, объединяя все её интервалы, создавая новый интервал с началом, равным минимальному началу среди всех интервалов в компоненте, и концом, равным максимальному концу.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив интервалов, где intervals[i] = [starti, endi]. Объедините все перекрывающиеся интервалы и верните массив неперекрывающихся интервалов, которые покрывают все интервалы во входных данных.
Пример:
Input: intervals = [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlap, merge them into [1,6].
Имея представленную интуицию, мы можем изобразить граф в виде списка смежности, вставляя направленные ребра в обоих направлениях, чтобы симулировать неориентированные ребра.
Для определения, в какой компоненте связности находится каждый узел, мы выполняем обходы графа от произвольных непосещенных узлов до тех пор, пока все узлы не будут посещены. Для эффективности мы храним посещенные узлы в множестве (Set), что позволяет проводить проверки на принадлежность и вставку за константное время.
Наконец, мы рассматриваем каждую связную компоненту, объединяя все её интервалы, создавая новый интервал с началом, равным минимальному началу среди всех интервалов в компоненте, и концом, равным максимальному концу.
class Solution {
private fun overlap(a: IntArray, b: IntArray): Boolean {
return a[0] <= b[1] && b[0] <= a[1]
}
private fun buildGraph(intervals: Array<IntArray>): HashMap<List<Int>, MutableList<IntArray>> {
val graph = HashMap<List<Int>, MutableList<IntArray>>()
for (i in intervals.indices) {
for (j in i + 1 until intervals.size) {
if (overlap(intervals[i], intervals[j])) {
graph.getOrPut(intervals[i].toList()) { mutableListOf() }.add(intervals[j])
graph.getOrPut(intervals[j].toList()) { mutableListOf() }.add(intervals[i])
}
}
}
return graph
}
private fun mergeNodes(nodes: List<IntArray>): IntArray {
val minStart = nodes.minOf { it[0] }
val maxEnd = nodes.maxOf { it[1] }
return intArrayOf(minStart, maxEnd)
}
private fun getComponents(
graph: HashMap<List<Int>, MutableList<IntArray>>,
intervals: Array<IntArray>
): Pair<HashMap<Int, MutableList<IntArray>>, Int> {
val visited = mutableSetOf<List<Int>>()
var compNumber = 0
val nodesInComp = HashMap<Int, MutableList<IntArray>>()
fun markComponentDFS(start: IntArray) {
val stack = mutableListOf(start)
while (stack.isNotEmpty()) {
val node = stack.removeLast().toList()
if (node !in visited) {
visited.add(node)
nodesInComp.getOrPut(compNumber) { mutableListOf() }.add(start)
graph[node]?.forEach { stack.add(it) }
}
}
}
for (interval in intervals) {
if (interval.toList() !in visited) {
markComponentDFS(interval)
compNumber++
}
}
return Pair(nodesInComp, compNumber)
}
fun merge(intervals: Array<IntArray>): Array<IntArray> {
val (graph, nodesInComp, numberComps) = buildGraph(intervals).let {
val (nodesInComp, numberComps) = getComponents(it, intervals)
Triple(it, nodesInComp, numberComps)
}
return Array(numberComps) { comp ->
mergeNodes(nodesInComp[comp]!!)
}
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 756. Pyramid Transition Matrix
Сложность: medium
Вы складываете блоки так, чтобы получилась пирамида. Каждый блок имеет цвет, который представлен одной буквой. Каждый ряд блоков содержит на один блок меньше, чем ряд под ним, и располагается по центру сверху. Чтобы пирамида выглядела эстетично, допускаются только определенные треугольные узоры. Треугольный узор состоит из одного блока, уложенного поверх двух блоков. Шаблоны задаются в виде списка допустимых трехбуквенных строк, где первые два символа шаблона представляют левый и правый нижние блоки соответственно, а третий символ - верхний блок. Например, "ABC" представляет треугольный шаблон с блоком 'C', уложенным поверх блоков 'A' (слева) и 'B' (справа). Обратите внимание, что это отличается от "BAC", где "B" находится слева внизу, а "A" - справа внизу. Вы начинаете с нижнего ряда блоков bottom, заданного в виде одной строки, который вы должны использовать в качестве основания пирамиды. Учитывая bottom и allowed, верните true, если вы можете построить пирамиду до самой вершины так, чтобы каждый треугольный узор в пирамиде был в allowed, или false в противном случае.
Пример:
👨💻 Алгоритм:
1⃣ Создайте структуру данных для хранения допустимых треугольных узоров.
2⃣ Напишите рекурсивную функцию, которая проверяет возможность построения следующего уровня пирамиды.
3⃣ Начните с нижнего уровня пирамиды и используйте рекурсию для построения каждого следующего уровня, проверяя каждый треугольный узор на допустимость.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вы складываете блоки так, чтобы получилась пирамида. Каждый блок имеет цвет, который представлен одной буквой. Каждый ряд блоков содержит на один блок меньше, чем ряд под ним, и располагается по центру сверху. Чтобы пирамида выглядела эстетично, допускаются только определенные треугольные узоры. Треугольный узор состоит из одного блока, уложенного поверх двух блоков. Шаблоны задаются в виде списка допустимых трехбуквенных строк, где первые два символа шаблона представляют левый и правый нижние блоки соответственно, а третий символ - верхний блок. Например, "ABC" представляет треугольный шаблон с блоком 'C', уложенным поверх блоков 'A' (слева) и 'B' (справа). Обратите внимание, что это отличается от "BAC", где "B" находится слева внизу, а "A" - справа внизу. Вы начинаете с нижнего ряда блоков bottom, заданного в виде одной строки, который вы должны использовать в качестве основания пирамиды. Учитывая bottom и allowed, верните true, если вы можете построить пирамиду до самой вершины так, чтобы каждый треугольный узор в пирамиде был в allowed, или false в противном случае.
Пример:
Input: bottom = "BCD", allowed = ["BCC","CDE","CEA","FFF"]
Output: true
class Solution {
fun pyramidTransition(bottom: String, allowed: List<String>): Boolean {
val allowedDict = mutableMapOf<String, MutableList<Char>>()
for (pattern in allowed) {
val key = pattern.substring(0, 2)
val value = pattern[2]
allowedDict.computeIfAbsent(key) { mutableListOf() }.add(value)
}
return canBuild(bottom, allowedDict)
}
private fun canBuild(currentLevel: String, allowedDict: Map<String, List<Char>>): Boolean {
if (currentLevel.length == 1) return true
val nextLevelOptions = mutableListOf<List<Char>>()
for (i in 0 until currentLevel.length - 1) {
val key = currentLevel.substring(i, i + 2)
if (!allowedDict.containsKey(key)) return false
nextLevelOptions.add(allowedDict[key]!!)
}
return canBuildNextLevel(nextLevelOptions, 0, "", allowedDict)
}
private fun canBuildNextLevel(options: List<List<Char>>, index: Int, nextLevel: String, allowedDict: Map<String, List<Char>>): Boolean {
if (index == options.size) return canBuild(nextLevel, allowedDict)
for (option in options[index]) {
if (canBuildNextLevel(options, index + 1, nextLevel + option, allowedDict)) return true
}
return false
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 65. Valid Number
Сложность: hard
Учитывая строку s, определите, является ли s валидным числом.
Например, все следующие строки являются действительными числами: "2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789". В то время как следующие строки не являются валидными числами: "abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53".
Формально, валидное число определяется с использованием одного из следующих определений:
Целое число с необязательным показателем степени.
Десятичное число с необязательным показателем степени.
Целое число определяется необязательным знаком '-' или '+' за которым следуют цифры.
Десятичное число определяется необязательным знаком '-' или '+' и одним из следующих определений:
Цифры, за которыми следует точка '.'.
Цифры, за которыми следует точка '.', за которой следуют цифры.
Точка '.', за которой следуют цифры.
Показатель степени определяется с помощью обозначения показателя степени 'e' или 'E', за которым следует целое число.
Цифры определяются как одна или более цифр.
Пример:
👨💻 Алгоритм:
1⃣ Объявите три переменные: seenDigit, seenExponent и seenDot, установив их все в false. Перебирайте символы входной строки. Если символ является цифрой, установите seenDigit в true.
2⃣ Если символ является знаком (+ или -), проверьте, является ли он первым символом ввода или предшествует ли он показателю степени (экспоненте). Если нет, верните false. Если символ является экспонентой (e или E), сначала проверьте, была ли уже видна экспонента или еще не было увидено ни одной цифры. Если что-то из этого верно, верните false. В противном случае установите seenExponent в true и сбросьте seenDigit, потому что после экспоненты должно следовать новое целое число.
3⃣ Если символ — точка (.), проверьте, были ли уже видны точка или экспонента. Если да, верните false. Иначе установите seenDot в true. Если символ чему-то иначе, верните false. В конце верните значение seenDigit, потому что, например, ввод вида "21e" должен быть признан недействительным, если после e не следуют цифры.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Учитывая строку s, определите, является ли s валидным числом.
Например, все следующие строки являются действительными числами: "2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789". В то время как следующие строки не являются валидными числами: "abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53".
Формально, валидное число определяется с использованием одного из следующих определений:
Целое число с необязательным показателем степени.
Десятичное число с необязательным показателем степени.
Целое число определяется необязательным знаком '-' или '+' за которым следуют цифры.
Десятичное число определяется необязательным знаком '-' или '+' и одним из следующих определений:
Цифры, за которыми следует точка '.'.
Цифры, за которыми следует точка '.', за которой следуют цифры.
Точка '.', за которой следуют цифры.
Показатель степени определяется с помощью обозначения показателя степени 'e' или 'E', за которым следует целое число.
Цифры определяются как одна или более цифр.
Пример:
Input: s = "0"
Output: true
class Solution {
fun isNumber(s: String): Boolean {
var seenDigit = false
var seenExponent = false
var seenDot = false
for ((i, c) in s.withIndex()) {
when {
c.isDigit() -> seenDigit = true
c == '+' || c == '-' -> {
if (i > 0 && s[i - 1] != 'e' && s[i - 1] != 'E') {
return false
}
}
c == 'e' || c == 'E' -> {
if (seenExponent || !seenDigit) {
return false
}
seenExponent = true
seenDigit = false // Reset seenDigit after exponent
}
c == '.' -> {
if (seenDot || seenExponent) {
return false
}
seenDot = true
}
else -> return false
}
}
return seenDigit
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
🎉 easyoffer 2.0 — релиз уже в этом месяце!
Вас ждут новые фичи, о которых мы ранее даже не упоминали. Они сделают путь к офферам ещё быстрее и эффективнее. Расскажу о них чуть позже 👀
В честь запуска мы готовим ограниченную акцию:
Первые 500 покупателей получат:
🚀 PRO тариф на 1 год с 50% скидкой
Что нужно сделать:
🔔 Подпишитесь на этот Telegram-канал, чтобы первыми узнать о старте релиза. Сообщение появится в нем раньше, чем где-либо еще — вы успеете попасть в число первых 500 и получить максимальную выгоду. 🎁 А еще только для подписчиков канала ценный бонус в подарок к PRO тарифу.
📅 Официальный запуск — уже совсем скоро.
Следите за новостями и не пропустите старт!
Вас ждут новые фичи, о которых мы ранее даже не упоминали. Они сделают путь к офферам ещё быстрее и эффективнее. Расскажу о них чуть позже 👀
В честь запуска мы готовим ограниченную акцию:
Первые 500 покупателей получат:
🚀 PRO тариф на 1 год с 50% скидкой
Что нужно сделать:
🔔 Подпишитесь на этот Telegram-канал, чтобы первыми узнать о старте релиза. Сообщение появится в нем раньше, чем где-либо еще — вы успеете попасть в число первых 500 и получить максимальную выгоду. 🎁 А еще только для подписчиков канала ценный бонус в подарок к PRO тарифу.
📅 Официальный запуск — уже совсем скоро.
Следите за новостями и не пропустите старт!
Задача: 268. Missing Number
Сложность: easy
Дан массив nums, содержащий n различных чисел в диапазоне [0, n]. Верните единственное число в этом диапазоне, которого нет в массиве.
Пример:
👨💻 Алгоритм:
1⃣ Сначала отсортируйте массив nums.
2⃣ Проверьте особые случаи: убедитесь, что число 0 находится в начале массива, а число n — в конце.
3⃣ Пройдитесь по отсортированному массиву и для каждого индекса проверьте, что число на этом индексе соответствует ожидаемому (предыдущее число плюс один). Как только вы обнаружите несоответствие, верните ожидаемое число.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан массив nums, содержащий n различных чисел в диапазоне [0, n]. Верните единственное число в этом диапазоне, которого нет в массиве.
Пример:
Input: nums = [3,0,1]
Output: 2
Explanation: n = 3 since there are 3 numbers, so all numbers are in the range [0,3]. 2 is the missing number in the range since it does not appear in nums.
class Solution {
fun missingNumber(nums: IntArray): Int {
nums.sort()
if (nums.last() != nums.size) {
return nums.size
} else if (nums.first() != 0) {
return 0
}
for (i in 1 until nums.size) {
val expectedNum = nums[i - 1] + 1
if (nums[i] != expectedNum) {
return expectedNum
}
}
return -1
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
Задача: 936. Stamping The Sequence
Сложность: hard
Вам даны две строки stamp и target. Изначально имеется строка s длины target.length со всеми s[i] == '?'. За один ход вы можете поместить штамп над s и заменить каждую букву в s на соответствующую букву из штампа. Например, если штамп = "abc" и target = "abcba", то s изначально будет "?????". За один ход вы можете: поместить штамп в индекс 0 s, чтобы получить "abc??", поместить штамп в индекс 1 s, чтобы получить "?abc?", или поместить штамп в индекс 2 s, чтобы получить "??abc". Обратите внимание, что штамп должен полностью находиться в границах s, чтобы штамповать (то есть вы не можете поместить штамп в индекс 3 s). Мы хотим преобразовать s в цель, используя не более 10 * target.length ходов. Верните массив индекса самой левой буквы, которая штампуется на каждом ходу. Если мы не можем получить цель из s за 10 * target.length оборотов, верните пустой массив
Пример:
👨💻 Алгоритм:
1⃣ Инициализировать переменные:
s как массив символов '?', длиной target.length.
res как список для хранения результатов.
done как массив булевых значений для отслеживания того, какие позиции уже штампованы.
target как массив символов для удобства.
2⃣ Использовать функцию canStamp для проверки, можно ли штамповать stamp в target начиная с индекса i.
Использовать функцию doStamp для штампования stamp в target начиная с индекса i.
Повторять шаги, пока штампы возможны или достигнут максимум ходов (10 * target.length):
Перебрать все возможные начальные позиции для штампа.
Проверить, можно ли штамповать в текущей позиции.
Если можно, штамповать и добавить индекс в res.
3⃣ Если все символы в s соответствуют символам в target, вернуть массив res в обратном порядке. Иначе, вернуть пустой массив.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Вам даны две строки stamp и target. Изначально имеется строка s длины target.length со всеми s[i] == '?'. За один ход вы можете поместить штамп над s и заменить каждую букву в s на соответствующую букву из штампа. Например, если штамп = "abc" и target = "abcba", то s изначально будет "?????". За один ход вы можете: поместить штамп в индекс 0 s, чтобы получить "abc??", поместить штамп в индекс 1 s, чтобы получить "?abc?", или поместить штамп в индекс 2 s, чтобы получить "??abc". Обратите внимание, что штамп должен полностью находиться в границах s, чтобы штамповать (то есть вы не можете поместить штамп в индекс 3 s). Мы хотим преобразовать s в цель, используя не более 10 * target.length ходов. Верните массив индекса самой левой буквы, которая штампуется на каждом ходу. Если мы не можем получить цель из s за 10 * target.length оборотов, верните пустой массив
Пример:
Input: stamp = "abc", target = "ababc"
Output: [0,2]
s как массив символов '?', длиной target.length.
res как список для хранения результатов.
done как массив булевых значений для отслеживания того, какие позиции уже штампованы.
target как массив символов для удобства.
Использовать функцию doStamp для штампования stamp в target начиная с индекса i.
Повторять шаги, пока штампы возможны или достигнут максимум ходов (10 * target.length):
Перебрать все возможные начальные позиции для штампа.
Проверить, можно ли штамповать в текущей позиции.
Если можно, штамповать и добавить индекс в res.
class Solution {
fun movesToStamp(stamp: String, target: String): IntArray {
val s = stamp.toCharArray()
val t = target.toCharArray()
val m = s.size
val n = t.size
val res = mutableListOf<Int>()
val done = BooleanArray(n)
fun canStamp(i: Int): Boolean {
for (j in 0 until m) {
if (t[i + j] != '?' && t[i + j] != s[j]) {
return false
}
}
return true
}
fun doStamp(i: Int) {
for (j in 0 until m) {
t[i + j] = '?'
}
res.add(i)
done[i] = true
}
var changed = true
while (changed) {
changed = false
for (i in 0..(n - m)) {
if (!done[i] && canStamp(i)) {
doStamp(i)
changed = true
}
}
}
return if (t.all { it == '?' }) res.reversed().toIntArray() else IntArray(0)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 836. Rectangle Overlap
Сложность: easy
Прямоугольник, выровненный по осям, представляется в виде списка [x1, y1, x2, y2], где (x1, y1) — координата его нижнего левого угла, а (x2, y2) — координата его верхнего правого угла. Его верхняя и нижняя грани параллельны оси X, а левая и правая грани параллельны оси Y.
Два прямоугольника перекрываются, если площадь их пересечения положительна. Для ясности, два прямоугольника, которые касаются только в углу или по краям, не перекрываются.
Даны два выровненных по осям прямоугольника rec1 и rec2, вернуть true, если они перекрываются, в противном случае вернуть false.
Пример:
👨💻 Алгоритм:
1⃣ Рассчитайте ширину пересечения: пересечение по оси x положительно, если min(rec1[2], rec2[2]) > max(rec1[0], rec2[0]).
2⃣ Рассчитайте высоту пересечения: пересечение по оси y положительно, если min(rec1[3], rec2[3]) > max(rec1[1], rec2[1]).
3⃣ Если и ширина, и высота пересечения положительны, прямоугольники перекрываются.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Прямоугольник, выровненный по осям, представляется в виде списка [x1, y1, x2, y2], где (x1, y1) — координата его нижнего левого угла, а (x2, y2) — координата его верхнего правого угла. Его верхняя и нижняя грани параллельны оси X, а левая и правая грани параллельны оси Y.
Два прямоугольника перекрываются, если площадь их пересечения положительна. Для ясности, два прямоугольника, которые касаются только в углу или по краям, не перекрываются.
Даны два выровненных по осям прямоугольника rec1 и rec2, вернуть true, если они перекрываются, в противном случае вернуть false.
Пример:
Input: rec1 = [0,0,2,2], rec2 = [1,1,3,3]
Output: true
class Solution {
fun isRectangleOverlap(rec1: IntArray, rec2: IntArray): Boolean {
return minOf(rec1[2], rec2[2]) > maxOf(rec1[0], rec2[0]) &&
minOf(rec1[3], rec2[3]) > maxOf(rec1[1], rec2[1])
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 100. Same Tree
Сложность: easy
Даны корни двух бинарных деревьев p и q. Напишите функцию, чтобы проверить, одинаковы ли они.
Два бинарных дерева считаются одинаковыми, если они структурно идентичны, и узлы имеют одинаковые значения.
Пример:
👨💻 Алгоритм:
1⃣ Проверяем, равны ли оба узла
2⃣ Если только один из узлов
3⃣ Сравниваем значения текущих узлов и рекурсивно проверяем дочерние узлы
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Даны корни двух бинарных деревьев p и q. Напишите функцию, чтобы проверить, одинаковы ли они.
Два бинарных дерева считаются одинаковыми, если они структурно идентичны, и узлы имеют одинаковые значения.
Пример:
Input: p = [1,2,3], q = [1,2,3]
Output: true
null null, деревья не равны class TreeNode(var value: Int, var left: TreeNode? = null, var right: TreeNode? = null)
class Solution {
fun isSameTree(p: TreeNode?, q: TreeNode?): Boolean {
if (p == null && q == null) {
return true
}
if (p == null || q == null) {
return false
}
if (p.value != q.value) {
return false
}
return isSameTree(p.right, q.right) && isSameTree(p.left, q.left)
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1258. Synonymous Sentences
Сложность: medium
Вам дан список эквивалентных пар строк synonyms, где synonyms[i] = [si, ti] означает, что si и ti являются эквивалентными строками. Вам также дан текст предложения. Верните все возможные синонимичные предложения, отсортированные лексикографически.
Пример:
👨💻 Алгоритм:
1⃣ Построить граф синонимов, используя структуру данных, такую как Union-Find или просто с использованием DFS/BFS.
2⃣ Пройти по каждому слову в предложении и найти все возможные синонимы.
Сгенерировать все возможные комбинации предложений.
3⃣ Отсортировать полученные предложения лексикографически.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан список эквивалентных пар строк synonyms, где synonyms[i] = [si, ti] означает, что si и ti являются эквивалентными строками. Вам также дан текст предложения. Верните все возможные синонимичные предложения, отсортированные лексикографически.
Пример:
Input: synonyms = [["happy","joy"],["sad","sorrow"],["joy","cheerful"]], text = "I am happy today but was sad yesterday"
Output: ["I am cheerful today but was sad yesterday","I am cheerful today but was sorrow yesterday","I am happy today but was sad yesterday","I am happy today but was sorrow yesterday","I am joy today but was sad yesterday","I am joy today but was sorrow yesterday"]
Сгенерировать все возможные комбинации предложений.
class Solution {
fun generateSentences(synonyms: List<List<String>>, text: String): List<String> {
val graph = mutableMapOf<String, MutableSet<String>>()
for (pair in synonyms) {
graph.getOrPut(pair[0]) { mutableSetOf() }.add(pair[1])
graph.getOrPut(pair[1]) { mutableSetOf() }.add(pair[0])
}
val words = text.split(" ")
val synonymGroups = words.map { findSynonyms(graph, it) }
val sentences = mutableListOf<String>()
generate(sentences, synonymGroups, StringBuilder(), 0)
return sentences.sorted()
}
private fun findSynonyms(graph: Map<String, Set<String>>, word: String): List<String> {
val synonyms = mutableSetOf<String>()
val stack = ArrayDeque<String>()
stack.push(word)
while (stack.isNotEmpty()) {
val w = stack.pop()
if (synonyms.add(w)) {
stack.addAll(graph[w] ?: emptySet())
}
}
return synonyms.toList().sorted()
}
private fun generate(sentences: MutableList<String>, groups: List<List<String>>, sentence: StringBuilder, index: Int) {
if (index == groups.size) {
sentences.add(sentence.toString().trim())
return
}
val len = sentence.length
for (word in groups[index]) {
sentence.append(" ").append(word)
generate(sentences, groups, sentence, index + 1)
sentence.setLength(len)
}
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM