Задача: 743. Network Delay Time
Сложность: medium
Дана сеть из узлов, помеченных от 1 до n. Также дано times - список времен прохождения сигнала в виде направленных ребер times[i] = (ui, vi, wi), где ui - исходный узел, vi - целевой узел, а wi - время прохождения сигнала от источника до цели. Мы пошлем сигнал из заданного узла k. Верните минимальное время, которое потребуется всем узлам, чтобы получить сигнал. Если все узлы не могут получить сигнал, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Представьте граф в виде списка смежности.
2⃣ Используйте алгоритм Дейкстры для нахождения кратчайших путей от узла k до всех других узлов.
3⃣ Найдите максимальное значение среди кратчайших путей к узлам. Если какой-либо узел недостижим, верните -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дана сеть из узлов, помеченных от 1 до n. Также дано times - список времен прохождения сигнала в виде направленных ребер times[i] = (ui, vi, wi), где ui - исходный узел, vi - целевой узел, а wi - время прохождения сигнала от источника до цели. Мы пошлем сигнал из заданного узла k. Верните минимальное время, которое потребуется всем узлам, чтобы получить сигнал. Если все узлы не могут получить сигнал, верните -1.
Пример:
Input: times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2
Output: 2
import java.util.*
fun networkDelayTime(times: Array<IntArray>, n: Int, k: Int): Int {
val graph = mutableMapOf<Int, MutableList<Pair<Int, Int>>>()
for (i in 1..n) {
graph[i] = mutableListOf()
}
for (time in times) {
graph[time[0]]?.add(Pair(time[1], time[2]))
}
val minHeap = PriorityQueue<Pair<Int, Int>>(compareBy { it.first })
minHeap.add(Pair(0, k))
val minTime = mutableMapOf<Int, Int>()
for (i in 1..n) {
minTime[i] = Int.MAX_VALUE
}
minTime[k] = 0
while (minHeap.isNotEmpty()) {
val (time, node) = minHeap.poll()
graph[node]?.forEach { (neighbor, t) ->
val newTime = time + t
if (newTime < minTime[neighbor]!!) {
minTime[neighbor] = newTime
minHeap.add(Pair(newTime, neighbor))
}
}
}
val maxTime = minTime.values.maxOrNull()!!
return if (maxTime == Int.MAX_VALUE) -1 else maxTime
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 600. Non-negative Integers without Consecutive Ones
Сложность: Hard
Дано положительное целое число n, верните количество чисел в диапазоне [0, n], бинарные представления которых не содержат последовательных единиц.
Пример:
👨💻 Алгоритм:
1⃣ Простой метод заключается в переборе всех чисел от 1 до num. Для каждого текущего выбранного числа проверяем все соседние позиции, чтобы выяснить, содержит ли число две последовательные единицы. Если не содержит, увеличиваем количество чисел без последовательных единиц.
2⃣ Чтобы проверить, существует ли 1 на позиции x (считая от младшего значащего бита), в текущем числе n, поступаем следующим образом. Сдвигаем двоичную 1 x−1 раз влево, чтобы получить число y, которое имеет 1 только на x-й позиции. Логическое И числа n и y даст результат 1 только если n содержит 1 на позиции x.
3⃣ В конце подсчитываем и возвращаем количество чисел в диапазоне [0, n], не содержащих последовательных единиц.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: Hard
Дано положительное целое число n, верните количество чисел в диапазоне [0, n], бинарные представления которых не содержат последовательных единиц.
Пример:
Input: n = 5
Output: 5
Explanation:
Here are the non-negative integers <= 5 with their corresponding binary representations:
0 : 0
1 : 1
2 : 10
3 : 11
4 : 100
5 : 101
Among them, only integer 3 disobeys the rule (two consecutive ones) and the other 5 satisfy the rule.
class Solution {
fun findIntegers(num: Int): Int {
var count = 0
for (i in 0..num) {
if (check(i)) {
count++
}
}
return count
}
fun check(n: Int): Boolean {
var i = 31
while (i > 0) {
if ((n and (1 shl i)) != 0 && (n and (1 shl (i - 1))) != 0) {
return false
}
i--
}
return true
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 284. Peeking Iterator
Сложность: medium
Создайте итератор, который поддерживает операцию peek (просмотр следующего элемента) на существующем итераторе, помимо операций hasNext (проверка наличия следующего элемента) и next (получение следующего элемента).
Реализуйте класс PeekingIterator:
PeekingIterator(Iterator<int> nums): Инициализирует объект с заданным итератором целых чисел.
int next(): Возвращает следующий элемент в массиве и перемещает указатель на следующий элемент.
boolean hasNext(): Возвращает true, если в массиве еще есть элементы.
int peek(): Возвращает следующий элемент в массиве без перемещения указателя.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация итератора:
В конструкторе класса PeekingIterator инициализируйте итератор и проверьте, есть ли следующий элемент. Если есть, установите его как next, иначе установите next в null.
2⃣ Операция peek:
Метод peek возвращает значение next, не перемещая указатель итератора.
3⃣ Операции next и hasNext:
Метод next возвращает текущее значение next, обновляет next к следующему элементу в итераторе и перемещает указатель итератора. Если нет следующего элемента, бросает исключение NoSuchElementException.
Метод hasNext возвращает true, если next не равно null, и false в противном случае.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Создайте итератор, который поддерживает операцию peek (просмотр следующего элемента) на существующем итераторе, помимо операций hasNext (проверка наличия следующего элемента) и next (получение следующего элемента).
Реализуйте класс PeekingIterator:
PeekingIterator(Iterator<int> nums): Инициализирует объект с заданным итератором целых чисел.
int next(): Возвращает следующий элемент в массиве и перемещает указатель на следующий элемент.
boolean hasNext(): Возвращает true, если в массиве еще есть элементы.
int peek(): Возвращает следующий элемент в массиве без перемещения указателя.
Пример:
Input
["PeekingIterator", "next", "peek", "next", "next", "hasNext"]
[[[1, 2, 3]], [], [], [], [], []]
Output
[null, 1, 2, 2, 3, false]
Explanation
PeekingIterator peekingIterator = new PeekingIterator([1, 2, 3]); // [1,2,3]
peekingIterator.next(); // return 1, the pointer moves to the next element [1,2,3].
peekingIterator.peek(); // return 2, the pointer does not move [1,2,3].
peekingIterator.next(); // return 2, the pointer moves to the next element [1,2,3]
peekingIterator.next(); // return 3, the pointer moves to the next element [1,2,3]
peekingIterator.hasNext(); // return False
В конструкторе класса PeekingIterator инициализируйте итератор и проверьте, есть ли следующий элемент. Если есть, установите его как next, иначе установите next в null.
Метод peek возвращает значение next, не перемещая указатель итератора.
Метод next возвращает текущее значение next, обновляет next к следующему элементу в итераторе и перемещает указатель итератора. Если нет следующего элемента, бросает исключение NoSuchElementException.
Метод hasNext возвращает true, если next не равно null, и false в противном случае.
class PeekingIterator(nums: Iterator<Int>) : Iterator<Int> {
private val iterator = nums
private var nextElement: Int? = if (iterator.hasNext()) iterator.next() else null
override fun next(): Int {
val currentElement = nextElement
nextElement = if (iterator.hasNext()) iterator.next() else null
return currentElement!!
}
override fun hasNext(): Boolean {
return nextElement != null
}
fun peek(): Int {
return nextElement!!
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 951. Flip Equivalent Binary Trees
Сложность: medium
Для бинарного дерева T мы можем определить операцию переворота следующим образом: выбираем любой узел и меняем местами левое и правое дочерние поддеревья. Бинарное дерево X эквивалентно бинарному дереву Y тогда и только тогда, когда мы можем сделать X равным Y после некоторого количества операций переворота. Учитывая корни двух бинарных деревьев root1 и root2, верните true, если эти два дерева эквивалентны перевороту, или false в противном случае.
Пример:
👨💻 Алгоритм:
1⃣ Если оба дерева пусты, они эквивалентны, вернуть true. Если одно дерево пустое, а другое нет, они не эквивалентны, вернуть false.
2⃣ Если значения корней деревьев не совпадают, вернуть false.
Проверить два условия:
Левое поддерево первого дерева эквивалентно левому поддереву второго дерева и правое поддерево первого дерева эквивалентно правому поддереву второго дерева.
Левое поддерево первого дерева эквивалентно правому поддереву второго дерева и правое поддерево первого дерева эквивалентно левому поддереву второго дерева.
3⃣ Вернуть true, если выполняется хотя бы одно из этих условий.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Для бинарного дерева T мы можем определить операцию переворота следующим образом: выбираем любой узел и меняем местами левое и правое дочерние поддеревья. Бинарное дерево X эквивалентно бинарному дереву Y тогда и только тогда, когда мы можем сделать X равным Y после некоторого количества операций переворота. Учитывая корни двух бинарных деревьев root1 и root2, верните true, если эти два дерева эквивалентны перевороту, или false в противном случае.
Пример:
Input: root1 = [1,2,3,4,5,6,null,null,null,7,8], root2 = [1,3,2,null,6,4,5,null,null,null,null,8,7]
Output: true
Проверить два условия:
Левое поддерево первого дерева эквивалентно левому поддереву второго дерева и правое поддерево первого дерева эквивалентно правому поддереву второго дерева.
Левое поддерево первого дерева эквивалентно правому поддереву второго дерева и правое поддерево первого дерева эквивалентно левому поддереву второго дерева.
class TreeNode(var `val`: Int) {
var left: TreeNode? = null
var right: TreeNode? = null
}
class Solution {
fun flipEquiv(root1: TreeNode?, root2: TreeNode?): Boolean {
if (root1 == null && root2 == null) return true
if (root1 == null || root2 == null) return false
if (root1.`val` != root2.`val`) return false
return (flipEquiv(root1.left, root2.left) && flipEquiv(root1.right, root2.right)) ||
(flipEquiv(root1.left, root2.right) && flipEquiv(root1.right, root2.left))
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 460. LFU Cache
Сложность: hard
Спроектируйте и реализуйте структуру данных для кеша с наименьшим количеством использования (Least Frequently Used, LFU).
Реализуйте класс LFUCache:
LFUCache(int capacity): Инициализирует объект с указанной вместимостью структуры данных.
int get(int key): Возвращает значение ключа, если ключ существует в кеше. В противном случае возвращает -1.
void put(int key, int value): Обновляет значение ключа, если он уже присутствует, или вставляет ключ, если его еще нет. Когда кеш достигает своей вместимости, он должен аннулировать и удалить ключ, используемый наименее часто, перед вставкой нового элемента. В этой задаче, если имеется несколько ключей с одинаковой частотой использования, аннулируется наименее недавно использованный ключ.
Чтобы определить наименее часто используемый ключ, для каждого ключа в кеше поддерживается счетчик использования. Ключ с наименьшим счетчиком использования является наименее часто используемым ключом.
Когда ключ впервые вставляется в кеш, его счетчик использования устанавливается на 1 (из-за операции put). Счетчик использования для ключа в кеше увеличивается при вызове операции get или put для этого ключа.
Функции get и put должны иметь среднюю временную сложность O(1).
Пример:
👨💻 Алгоритм:
1⃣ insert(int key, int frequency, int value):
Вставить пару частота-значение в cache с заданным ключом.
Получить LinkedHashSet, соответствующий данной частоте (по умолчанию пустой Set), и вставить в него ключ.
2⃣ int get(int key):
Если ключа нет в кеше, вернуть -1.
Получить частоту и значение из кеша.
Удалить ключ из LinkedHashSet, связанного с частотой.
Если minf == frequency и LinkedHashSet пуст, увеличить minf на 1 и удалить запись частоты из frequencies.
Вызвать insert(key, frequency + 1, value).
Вернуть значение.
3⃣ void put(int key, int value):
Если capacity <= 0, выйти.
Если ключ существует, обновить значение и вызвать get(key).
Если размер кеша равен capacity, удалить первый элемент из LinkedHashSet, связанного с minf, и из кеша.
Установить minf в 1.
Вызвать insert(key, 1, value).
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Спроектируйте и реализуйте структуру данных для кеша с наименьшим количеством использования (Least Frequently Used, LFU).
Реализуйте класс LFUCache:
LFUCache(int capacity): Инициализирует объект с указанной вместимостью структуры данных.
int get(int key): Возвращает значение ключа, если ключ существует в кеше. В противном случае возвращает -1.
void put(int key, int value): Обновляет значение ключа, если он уже присутствует, или вставляет ключ, если его еще нет. Когда кеш достигает своей вместимости, он должен аннулировать и удалить ключ, используемый наименее часто, перед вставкой нового элемента. В этой задаче, если имеется несколько ключей с одинаковой частотой использования, аннулируется наименее недавно использованный ключ.
Чтобы определить наименее часто используемый ключ, для каждого ключа в кеше поддерживается счетчик использования. Ключ с наименьшим счетчиком использования является наименее часто используемым ключом.
Когда ключ впервые вставляется в кеш, его счетчик использования устанавливается на 1 (из-за операции put). Счетчик использования для ключа в кеше увеличивается при вызове операции get или put для этого ключа.
Функции get и put должны иметь среднюю временную сложность O(1).
Пример:
Input
["LFUCache", "put", "put", "get", "put", "get", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [3], [4, 4], [1], [3], [4]]
Output
[null, null, null, 1, null, -1, 3, null, -1, 3, 4]
Вставить пару частота-значение в cache с заданным ключом.
Получить LinkedHashSet, соответствующий данной частоте (по умолчанию пустой Set), и вставить в него ключ.
Если ключа нет в кеше, вернуть -1.
Получить частоту и значение из кеша.
Удалить ключ из LinkedHashSet, связанного с частотой.
Если minf == frequency и LinkedHashSet пуст, увеличить minf на 1 и удалить запись частоты из frequencies.
Вызвать insert(key, frequency + 1, value).
Вернуть значение.
Если capacity <= 0, выйти.
Если ключ существует, обновить значение и вызвать get(key).
Если размер кеша равен capacity, удалить первый элемент из LinkedHashSet, связанного с minf, и из кеша.
Установить minf в 1.
Вызвать insert(key, 1, value).
class LFUCache(private val capacity: Int) {
private var minf = 0
private val cache = mutableMapOf<Int, Pair<Int, MutableIterator<Pair<Int, Int>>>>()
private val frequencies = mutableMapOf<Int, LinkedHashSet<Pair<Int, Int>>>()
private fun insert(key: Int, frequency: Int, value: Int) {
val freqSet = frequencies.getOrPut(frequency) { LinkedHashSet() }
freqSet.add(Pair(key, value))
cache[key] = Pair(frequency, freqSet.iterator())
}
fun get(key: Int): Int {
val entry = cache[key] ?: return -1
val (frequency, iter) = entry
val kv = iter.next()
frequencies[frequency]?.remove(kv)
if (frequencies[frequency]?.isEmpty() == true) {
frequencies.remove(frequency)
if (minf == frequency) minf++
}
insert(key, frequency + 1, kv.second)
return kv.second
}
fun put(key: Int, value: Int) {
if (capacity <= 0) return
if (cache.containsKey(key)) {
val (frequency, iter) = cache[key]!!
iter.next().second = value
get(key)
return
}
if (cache.size == capacity) {
val kv = frequencies[minf]?.iterator()?.next()
cache.remove(kv?.first)
frequencies[minf]?.remove(kv)
if (frequencies[minf]?.isEmpty() == true) frequencies.remove(minf)
}
minf = 1
insert(key, 1, value)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1273. Delete Tree Nodes
Сложность: medium
Дерево, укорененное в узле 0, задано следующим образом: количество узлов - nodes; значение i-го узла - value[i]; родитель i-го узла - parent[i]. Удалите все поддеревья, сумма значений узлов которых равна нулю. Верните количество оставшихся узлов в дереве.
Пример:
👨💻 Алгоритм:
1⃣ Постройте дерево из заданных узлов, значений и родителей.
2⃣ Используйте постфиксный обход для вычисления суммы значений в каждом поддереве и помечайте узлы для удаления, если их сумма равна нулю.
3⃣ Удалите отмеченные узлы и их поддеревья и верните количество оставшихся узлов.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дерево, укорененное в узле 0, задано следующим образом: количество узлов - nodes; значение i-го узла - value[i]; родитель i-го узла - parent[i]. Удалите все поддеревья, сумма значений узлов которых равна нулю. Верните количество оставшихся узлов в дереве.
Пример:
Input: nodes = 7, parent = [-1,0,0,1,2,2,2], value = [1,-2,4,0,-2,-1,-1]
Output: 2
class Solution {
fun deleteTreeNodes(nodes: Int, parent: IntArray, value: IntArray): Int {
val tree = mutableMapOf<Int, MutableList<Int>>()
for (i in 0 until nodes) {
tree.computeIfAbsent(parent[i]) { mutableListOf() }.add(i)
}
fun dfs(node: Int): Pair<Int, Int> {
var totalSum = value[node]
var totalCount = 1
tree[node]?.forEach { child ->
val (childSum, childCount) = dfs(child)
totalSum += childSum
totalCount += childCount
}
return if (totalSum == 0) Pair(0, 0) else Pair(totalSum, totalCount)
}
return dfs(0).second
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1136. Parallel Courses
Сложность: medium
Вам дано целое число n, которое указывает, что есть n курсов, обозначенных от 1 до n. Вам также дан массив relations, где relations[i] = [prevCoursei, nextCoursei], представляющий собой зависимость между курсами: курс prevCoursei должен быть пройден до курса nextCoursei.
За один семестр вы можете взять любое количество курсов, при условии, что вы прошли все необходимые предварительные курсы в предыдущем семестре для тех курсов, которые вы собираетесь взять.
Верните минимальное количество семестров, необходимых для прохождения всех курсов. Если нет способа пройти все курсы, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Постройте направленный граф из зависимостей (relations).
2⃣ Реализуйте функцию dfsCheckCycle для проверки наличия цикла в графе.
3⃣ Реализуйте функцию dfsMaxPath для вычисления длины самого длинного пути в графе. Если цикл найден, верните -1. Иначе верните длину самого длинного пути.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дано целое число n, которое указывает, что есть n курсов, обозначенных от 1 до n. Вам также дан массив relations, где relations[i] = [prevCoursei, nextCoursei], представляющий собой зависимость между курсами: курс prevCoursei должен быть пройден до курса nextCoursei.
За один семестр вы можете взять любое количество курсов, при условии, что вы прошли все необходимые предварительные курсы в предыдущем семестре для тех курсов, которые вы собираетесь взять.
Верните минимальное количество семестров, необходимых для прохождения всех курсов. Если нет способа пройти все курсы, верните -1.
Пример:
Input: n = 3, relations = [[1,3],[2,3]]
Output: 2
Explanation: The figure above represents the given graph.
In the first semester, you can take courses 1 and 2.
In the second semester, you can take course 3.
class Solution {
fun minimumSemesters(N: Int, relations: Array<IntArray>): Int {
val graph = Array(N + 1) { mutableListOf<Int>() }
for (relation in relations) {
graph[relation[0]].add(relation[1])
}
val visited = IntArray(N + 1)
for (node in 1..N) {
if (dfsCheckCycle(node, graph, visited) == -1) {
return -1
}
}
val visitedLength = IntArray(N + 1)
var maxLength = 1
for (node in 1..N) {
val length = dfsMaxPath(node, graph, visitedLength)
maxLength = maxOf(length, maxLength)
}
return maxLength
}
private fun dfsCheckCycle(node: Int, graph: Array<MutableList<Int>>, visited: IntArray): Int {
if (visited[node] != 0) {
return visited[node]
} else {
visited[node] = -1
}
for (endNode in graph[node]) {
if (dfsCheckCycle(endNode, graph, visited) == -1) {
return -1
}
}
visited[node] = 1
return 1
}
private fun dfsMaxPath(node: Int, graph: Array<MutableList<Int>>, visitedLength: IntArray): Int {
if (visitedLength[node] != 0) {
return visitedLength[node]
}
var maxLength = 1
for (endNode in graph[node]) {
val length = dfsMaxPath(endNode, graph, visitedLength)
maxLength = maxOf(length + 1, maxLength)
}
visitedLength[node] = maxLength
return maxLength
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 276. Paint Fence
Сложность: medium
Вы красите забор из n столбцов, используя k различных цветов. Вы должны красить столбы, следуя этим правилам:
Каждый столб должен быть окрашен в один цвет.
Не может быть трех или более подряд идущих столбцов одного цвета.
Учитывая два целых числа n и k, верните количество способов покрасить забор.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и определение вспомогательной функции:
Определить хеш-таблицу memo, где memo[i] представляет количество способов покрасить i столбцов.
Определить функцию totalWays, которая будет определять количество способов покрасить i столбцов.
2⃣ Реализация базы и проверка кэша:
В функции totalWays проверить базовые случаи: вернуть k, если i == 1, и вернуть k * k, если i == 2.
Проверить, рассчитан ли аргумент i и сохранен ли в memo. Если да, вернуть memo[i].
3⃣ Расчет с использованием рекуррентного соотношения:
В противном случае использовать рекуррентное соотношение для вычисления memo[i], сохранить результат в memo[i] и вернуть его.
Вызвать и вернуть totalWays(n).
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вы красите забор из n столбцов, используя k различных цветов. Вы должны красить столбы, следуя этим правилам:
Каждый столб должен быть окрашен в один цвет.
Не может быть трех или более подряд идущих столбцов одного цвета.
Учитывая два целых числа n и k, верните количество способов покрасить забор.
Пример:
Input: n = 3, k = 2
Output: 6
Explanation: All the possibilities are shown.
Note that painting all the posts red or all the posts green is invalid because there cannot be three posts in a row with the same color.
Определить хеш-таблицу memo, где memo[i] представляет количество способов покрасить i столбцов.
Определить функцию totalWays, которая будет определять количество способов покрасить i столбцов.
В функции totalWays проверить базовые случаи: вернуть k, если i == 1, и вернуть k * k, если i == 2.
Проверить, рассчитан ли аргумент i и сохранен ли в memo. Если да, вернуть memo[i].
В противном случае использовать рекуррентное соотношение для вычисления memo[i], сохранить результат в memo[i] и вернуть его.
Вызвать и вернуть totalWays(n).
class Solution {
fun numWays(n: Int, k: Int): Int {
if (n == 1) return k
var twoPostsBack = k
var onePostBack = k * k
for (i in 3..n) {
val curr = (k - 1) * (onePostBack + twoPostsBack)
twoPostsBack = onePostBack
onePostBack = curr
}
return onePostBack
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 485. Max Consecutive Ones
Сложность: Easy
Дан бинарный массив nums, верните максимальное количество последовательных единиц в массиве.
Пример:
👨💻 Алгоритм:
1⃣ Поддерживайте счетчик для подсчета единиц и увеличивайте его на 1 при встрече единицы.
2⃣ Когда встречаете ноль, используйте текущий счетчик единиц для нахождения максимального количества последовательных единиц на данный момент, затем сбросьте счетчик единиц на 0.
3⃣ В конце верните максимальное значение.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: Easy
Дан бинарный массив nums, верните максимальное количество последовательных единиц в массиве.
Пример:
Input: nums = [1,1,0,1,1,1]
Output: 3
Explanation: The first two digits or the last three digits are consecutive 1s. The maximum number of consecutive 1s is 3.
class Solution {
fun findMaxConsecutiveOnes(nums: IntArray): Int {
var count = 0
var maxCount = 0
for (num in nums) {
if (num == 1) {
count += 1
} else {
maxCount = maxOf(maxCount, count)
count = 0
}
}
return maxOf(maxCount, count)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 380. Insert Delete GetRandom O(1)
Сложность: medium
Реализуйте класс RandomizedSet:
RandomizedSet(): Инициализирует объект RandomizedSet.
bool insert(int val): Вставляет элемент val в множество, если его там нет. Возвращает true, если элемент отсутствовал, и false в противном случае.
bool remove(int val): Удаляет элемент val из множества, если он присутствует. Возвращает true, если элемент присутствовал, и false в противном случае.
int getRandom(): Возвращает случайный элемент из текущего множества элементов (гарантируется, что по крайней мере один элемент существует при вызове этого метода). Каждый элемент должен иметь равную вероятность быть возвращенным.
Вы должны реализовать функции класса таким образом, чтобы каждая функция работала в среднем за O(1) по времени.
Пример:
👨💻 Алгоритм:
1⃣ Создать словарь для хранения значений и их индексов, а также список для хранения значений.
2⃣ Метод insert(val): Проверить наличие значения в словаре. Если отсутствует, добавить значение в список и обновить словарь с новым индексом.
Метод remove(val): Проверить наличие значения в словаре. Если присутствует, заменить удаляемое значение последним элементом списка, обновить его индекс в словаре, удалить последний элемент из списка и удалить значение из словаря.
3⃣ Метод getRandom(): Возвращать случайный элемент из списка, используя встроенную функцию генерации случайных чисел.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Реализуйте класс RandomizedSet:
RandomizedSet(): Инициализирует объект RandomizedSet.
bool insert(int val): Вставляет элемент val в множество, если его там нет. Возвращает true, если элемент отсутствовал, и false в противном случае.
bool remove(int val): Удаляет элемент val из множества, если он присутствует. Возвращает true, если элемент присутствовал, и false в противном случае.
int getRandom(): Возвращает случайный элемент из текущего множества элементов (гарантируется, что по крайней мере один элемент существует при вызове этого метода). Каждый элемент должен иметь равную вероятность быть возвращенным.
Вы должны реализовать функции класса таким образом, чтобы каждая функция работала в среднем за O(1) по времени.
Пример:
Input
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"]
[[], [1], [2], [2], [], [1], [2], []]
Output
[null, true, false, true, 2, true, false, 2]
Метод remove(val): Проверить наличие значения в словаре. Если присутствует, заменить удаляемое значение последним элементом списка, обновить его индекс в словаре, удалить последний элемент из списка и удалить значение из словаря.
import kotlin.random.Random
class RandomizedSet {
private val dict = mutableMapOf<Int, Int>()
private val list = mutableListOf<Int>()
fun insert(val: Int): Boolean {
if (dict.containsKey(val)) {
return false
}
dict[val] = list.size
list.add(val)
return true
}
fun remove(val: Int): Boolean {
val index = dict[val] ?: return false
val lastElement = list.removeAt(list.size - 1)
if (index < list.size) {
list[index] = lastElement
dict[lastElement] = index
}
dict.remove(val)
return true
}
fun getRandom(): Int {
return list[Random.nextInt(list.size)]
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1020. Number of Enclaves
Сложность: medium
Вам дана двоичная матричная сетка m x n, где 0 обозначает морскую ячейку, а 1 - сухопутную. Ход состоит из перехода от одной сухопутной ячейки к другой соседней (в 4-х направлениях) или выхода за границу сетки. Верните количество сухопутных ячеек в сетке, для которых мы не можем выйти за границу сетки за любое количество ходов.
Пример:
👨💻 Алгоритм:
1⃣ Обработка граничных сухопутных ячеек:
Пройдитесь по всем ячейкам, которые находятся на границе сетки (первый и последний ряды, первый и последний столбцы). Если ячейка содержит 1, начните поиск в глубину (DFS) или поиск в ширину (BFS), чтобы пометить все достижимые из нее сухопутные ячейки как посещенные.
2⃣ Проверка всех ячеек:
Пройдите по всем ячейкам матрицы, считая количество сухопутных ячеек, которые не были посещены в предыдущем шаге.
3⃣ Возврат результата:
Верните количество не посещенных сухопутных ячеек.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дана двоичная матричная сетка m x n, где 0 обозначает морскую ячейку, а 1 - сухопутную. Ход состоит из перехода от одной сухопутной ячейки к другой соседней (в 4-х направлениях) или выхода за границу сетки. Верните количество сухопутных ячеек в сетке, для которых мы не можем выйти за границу сетки за любое количество ходов.
Пример:
Input: grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
Output: 3
Пройдитесь по всем ячейкам, которые находятся на границе сетки (первый и последний ряды, первый и последний столбцы). Если ячейка содержит 1, начните поиск в глубину (DFS) или поиск в ширину (BFS), чтобы пометить все достижимые из нее сухопутные ячейки как посещенные.
Пройдите по всем ячейкам матрицы, считая количество сухопутных ячеек, которые не были посещены в предыдущем шаге.
Верните количество не посещенных сухопутных ячеек.
class Solution {
fun numEnclaves(grid: Array<IntArray>): Int {
val m = grid.size
val n = grid[0].size
fun dfs(x: Int, y: Int) {
if (x < 0 || y < 0 || x >= m || y >= n || grid[x][y] != 1) {
return
}
grid[x][y] = 0
dfs(x + 1, y)
dfs(x - 1, y)
dfs(x, y + 1)
dfs(x, y - 1)
}
for (i in 0 until m) {
if (grid[i][0] == 1) {
dfs(i, 0)
}
if (grid[i][n - 1] == 1) {
dfs(i, n - 1)
}
}
for (j in 0 until n) {
if (grid[0][j] == 1) {
dfs(0, j)
}
if (grid[m - 1][j] == 1) {
dfs(m - 1, j)
}
}
var count = 0
for (i in 0 until m) {
for (j in 0 until n) {
if (grid[i][j] == 1) {
count += 1
}
}
}
return count
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1219. Path with Maximum Gold
Сложность: medium
В золотом руднике размером m x n каждая ячейка содержит целое число, представляющее количество золота в этой ячейке, или 0, если она пуста.
Верните максимальное количество золота, которое вы можете собрать при следующих условиях:
- Каждый раз, когда вы находитесь в ячейке, вы собираете всё золото из этой ячейки.
- Из вашей позиции вы можете сделать один шаг влево, вправо, вверх или вниз.
- Вы не можете посещать одну и ту же ячейку более одного раза.
- Никогда не посещайте ячейку с 0 золотом.
- Вы можете начинать и прекращать сбор золота с любой позиции в сетке, которая содержит золото.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и подготовка:
Инициализируйте константный массив DIRECTIONS для направления перемещений.
Определите количество строк и столбцов в сетке.
Инициализируйте переменную maxGold для хранения максимального количества собранного золота.
2⃣ Функция DFS и обратный трек:
Реализуйте функцию dfsBacktrack для поиска пути с максимальным золотом с помощью DFS и обратного трека.
Обрабатывайте базовый случай, проверяя выход за пределы сетки или ячейки без золота.
Пометьте текущую ячейку как посещённую и сохраните её значение.
Исследуйте каждую из четырёх смежных ячеек и обновите максимальное количество золота, если найден лучший путь.
Сбросьте текущую ячейку до её исходного значения для дальнейших исследований.
3⃣ Поиск максимального золота:
Используйте вложенные циклы для каждой ячейки в сетке, чтобы найти максимальное количество золота, начиная с этой ячейки, с помощью функции dfsBacktrack.
Обновите maxGold при нахождении лучшего пути.
Верните maxGold.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
В золотом руднике размером m x n каждая ячейка содержит целое число, представляющее количество золота в этой ячейке, или 0, если она пуста.
Верните максимальное количество золота, которое вы можете собрать при следующих условиях:
- Каждый раз, когда вы находитесь в ячейке, вы собираете всё золото из этой ячейки.
- Из вашей позиции вы можете сделать один шаг влево, вправо, вверх или вниз.
- Вы не можете посещать одну и ту же ячейку более одного раза.
- Никогда не посещайте ячейку с 0 золотом.
- Вы можете начинать и прекращать сбор золота с любой позиции в сетке, которая содержит золото.
Пример:
Input: grid = [[0,6,0],[5,8,7],[0,9,0]]
Output: 24
Explanation:
[[0,6,0],
[5,8,7],
[0,9,0]]
Path to get the maximum gold, 9 -> 8 -> 7.
Инициализируйте константный массив DIRECTIONS для направления перемещений.
Определите количество строк и столбцов в сетке.
Инициализируйте переменную maxGold для хранения максимального количества собранного золота.
Реализуйте функцию dfsBacktrack для поиска пути с максимальным золотом с помощью DFS и обратного трека.
Обрабатывайте базовый случай, проверяя выход за пределы сетки или ячейки без золота.
Пометьте текущую ячейку как посещённую и сохраните её значение.
Исследуйте каждую из четырёх смежных ячеек и обновите максимальное количество золота, если найден лучший путь.
Сбросьте текущую ячейку до её исходного значения для дальнейших исследований.
Используйте вложенные циклы для каждой ячейки в сетке, чтобы найти максимальное количество золота, начиная с этой ячейки, с помощью функции dfsBacktrack.
Обновите maxGold при нахождении лучшего пути.
Верните maxGold.
class Solution {
private val directions = intArrayOf(0, 1, 0, -1, 0)
fun getMaximumGold(grid: Array<IntArray>): Int {
val rows = grid.size
val cols = grid[0].size
var maxGold = 0
for (row in 0 until rows) {
for (col in 0 until cols) {
maxGold = maxOf(maxGold, dfsBacktrack(grid, rows, cols, row, col))
}
}
return maxGold
}
private fun dfsBacktrack(grid: Array<IntArray>, rows: Int, cols: Int, row: Int, col: Int): Int {
if (row < 0 || col < 0 || row >= rows || col >= cols || grid[row][col] == 0) {
return 0
}
val originalVal = grid[row][col]
grid[row][col] = 0
var maxGold = 0
for (i in 0 until 4) {
maxGold = maxOf(maxGold, dfsBacktrack(grid, rows, cols, row + directions[i], col + directions[i + 1]))
}
grid[row][col] = originalVal
return maxGold + originalVal
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 99. Recover Binary Search Tree
Сложность: medium
Вам дан корень бинарного дерева поиска (BST), в котором значения ровно двух узлов дерева были поменяны местами по ошибке. Восстановите дерево, не изменяя его структуру.
Пример:
👨💻 Алгоритм:
1⃣ Создайте симметричный обход дерева. Это должен быть почти отсортированный список, в котором поменяны местами только два элемента.
2⃣ Определите два поменянных местами элемента x и y в почти отсортированном массиве за линейное время.
3⃣ Повторно пройдите по дереву. Измените значение x на y и значение y на x.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан корень бинарного дерева поиска (BST), в котором значения ровно двух узлов дерева были поменяны местами по ошибке. Восстановите дерево, не изменяя его структуру.
Пример:
Input: root = [1,3,null,null,2]
Output: [3,1,null,null,2]
Explanation: 3 cannot be a left child of 1 because 3 > 1. Swapping 1 and 3 makes the BST valid.
class TreeNode(var value: Int, var left: TreeNode? = null, var right: TreeNode? = null)
class Solution {
fun recoverTree(root: TreeNode?) {
fun inorder(r: TreeNode?): List<Int> {
if (r == null) return emptyList()
return inorder(r.left) + r.value + inorder(r.right)
}
fun findTwoSwapped(nums: List<Int>): Pair<Int, Int> {
val n = nums.size
var x: Int? = null
var y: Int? = null
for (i in 0 until n - 1) {
if (nums[i + 1] < nums[i]) {
y = nums[i + 1]
if (x == null) {
x = nums[i]
} else {
break
}
}
}
return Pair(x!!, y!!)
}
fun recover(r: TreeNode?, x: Int, y: Int, count: IntArray) {
if (r == null || count[0] == 0) return
if (r.value == x || r.value == y) {
r.value = if (r.value == x) y else x
count[0]--
if (count[0] == 0) return
}
recover(r.left, x, y, count)
recover(r.right, x, y, count)
}
val nums = inorder(root)
val (x, y) = findTwoSwapped(nums)
recover(root, x, y, intArrayOf(2))
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1470. Shuffle the Array
Сложность: easy
Дан массив nums, состоящий из 2n элементов в форме [x1, x2, ..., xn, y1, y2, ..., yn].
Верните массив в форме [x1, y1, x2, y2, ..., xn, yn].
Пример:
👨💻 Алгоритм:
1⃣ Создайте массив result размером 2 * n.
2⃣ Итеративно пройдите по массиву nums от 0 до n - 1:
Сохраните элемент xi+1, то есть nums[i], в индекс 2 * i массива result.
Сохраните элемент yi+1, то есть nums[i + n], в индекс 2 * i + 1 массива result.
3⃣ Верните массив result.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан массив nums, состоящий из 2n элементов в форме [x1, x2, ..., xn, y1, y2, ..., yn].
Верните массив в форме [x1, y1, x2, y2, ..., xn, yn].
Пример:
Input: nums = [2,5,1,3,4,7], n = 3
Output: [2,3,5,4,1,7]
Explanation: Since x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 then the answer is [2,3,5,4,1,7].
Сохраните элемент xi+1, то есть nums[i], в индекс 2 * i массива result.
Сохраните элемент yi+1, то есть nums[i + n], в индекс 2 * i + 1 массива result.
class Solution {
fun shuffle(nums: IntArray, n: Int): IntArray {
val result = IntArray(2 * n)
for (i in 0 until n) {
result[2 * i] = nums[i]
result[2 * i + 1] = nums[n + i]
}
return result
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 190. Reverse Bits
Сложность: easy
Переверните биты заданного 32-битного беззнакового целого числа.
Пример:
👨💻 Алгоритм:
1⃣ Итерируем по байтам целого числа, используя побитовую операцию И (n & 0xff) с маской 11111111, чтобы извлечь крайний правый байт числа.
2⃣ Для каждого байта сначала переворачиваем биты внутри байта с помощью функции reverseByte(byte). Затем сдвигаем перевернутые биты на их окончательные позиции.
3⃣ В функции reverseByte(byte) используем технику мемоизации, которая сохраняет результат функции и возвращает его непосредственно при последующих вызовах с тем же входным значением. Мемоизация — это компромисс между использованием памяти и объемом вычислений.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Переверните биты заданного 32-битного беззнакового целого числа.
Пример:
Input: n = 00000010100101000001111010011100
Output: 964176192 (00111001011110000010100101000000)
Explanation: The input binary string 00000010100101000001111010011100 represents the unsigned integer 43261596, so return 964176192 which its binary representation is 00111001011110000010100101000000.
Example 2:
class Solution {
private val cache = mutableMapOf<UInt, UInt>()
fun reverseByte(byte: UInt): UInt {
return cache.getOrElse(byte) {
val value = ((byte * 0x0202020202u) and 0x010884422010u) % 1023u
cache[byte] = value
value
}
}
fun reverseBits(n: UInt): UInt {
var ret = 0u
var power = 24
var n = n
while (n != 0u) {
ret += reverseByte(n and 0xffu) shl power
n = n shr 8
power -= 8
}
return ret
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
Задача: 487. Max Consecutive Ones II
Сложность: medium
Дан бинарный массив nums, верните максимальное количество последовательных единиц в массиве, если можно перевернуть не более одного нуля.
Пример:
👨💻 Алгоритм:
1⃣ Для каждого возможного начала последовательности в массиве nums начните считать количество нулей.
2⃣ Для каждой последовательности проверяйте, сколько нулей содержится в ней. Если количество нулей не превышает одного, обновите максимальную длину последовательности единиц.
3⃣ Продолжайте проверять все возможные последовательности в массиве, и верните максимальную длину последовательности единиц, удовлетворяющую условию.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан бинарный массив nums, верните максимальное количество последовательных единиц в массиве, если можно перевернуть не более одного нуля.
Пример:
Input: nums = [1,0,1,1,0]
Output: 4
Explanation:
- If we flip the first zero, nums becomes [1,1,1,1,0] and we have 4 consecutive ones.
- If we flip the second zero, nums becomes [1,0,1,1,1] and we have 3 consecutive ones.
The max number of consecutive ones is 4.
class Solution {
fun findMaxConsecutiveOnes(nums: IntArray): Int {
var longestSequence = 0
for (left in nums.indices) {
var numZeroes = 0
for (right in left until nums.size) {
if (nums[right] == 0) {
numZeroes++
}
if (numZeroes <= 1) {
longestSequence = maxOf(longestSequence, right - left + 1)
}
}
}
return longestSequence
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 682. Baseball Game
Сложность: medium
Вы ведете учет очков в бейсбольной игре с необычными правилами. В начале игры у вас пустая запись.
Вам дается список строк operations, где operations[i] — это i-я операция, которую вы должны применить к записи, и она может быть одной из следующих:
Целое число x.
Записать новый счет, равный x.
'+'.
Записать новый счет, который является суммой двух предыдущих очков.
'D'.
Записать новый счет, который в два раза больше предыдущего очка.
'C'.
Аннулировать предыдущее очко, удалив его из записи.
Верните сумму всех очков в записи после применения всех операций.
Тестовые случаи сформированы таким образом, что ответ и все промежуточные вычисления умещаются в 32-битное целое число, и что все операции корректны.
Пример:
👨💻 Алгоритм:
1⃣ Поддерживайте значение каждого действительного раунда в стеке при обработке данных. Используйте стек, так как операции касаются только последнего или предпоследнего действительного раунда.
2⃣ Обрабатывайте каждую операцию из списка operations последовательно, выполняя соответствующее действие: добавление, суммирование, удвоение или удаление очков.
3⃣ После обработки всех операций верните сумму всех значений в стеке.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вы ведете учет очков в бейсбольной игре с необычными правилами. В начале игры у вас пустая запись.
Вам дается список строк operations, где operations[i] — это i-я операция, которую вы должны применить к записи, и она может быть одной из следующих:
Целое число x.
Записать новый счет, равный x.
'+'.
Записать новый счет, который является суммой двух предыдущих очков.
'D'.
Записать новый счет, который в два раза больше предыдущего очка.
'C'.
Аннулировать предыдущее очко, удалив его из записи.
Верните сумму всех очков в записи после применения всех операций.
Тестовые случаи сформированы таким образом, что ответ и все промежуточные вычисления умещаются в 32-битное целое число, и что все операции корректны.
Пример:
Input: ops = ["5","2","C","D","+"]
Output: 30
Explanation:
"5" - Add 5 to the record, record is now [5].
"2" - Add 2 to the record, record is now [5, 2].
"C" - Invalidate and remove the previous score, record is now [5].
"D" - Add 2 * 5 = 10 to the record, record is now [5, 10].
"+" - Add 5 + 10 = 15 to the record, record is now [5, 10, 15].
The total sum is 5 + 10 + 15 = 30.
class Solution {
fun calPoints(ops: Array<String>): Int {
val stack = mutableListOf<Int>()
for (op in ops) {
when (op) {
"+" -> {
val top = stack.removeAt(stack.size - 1)
val newTop = top + stack.last()
stack.add(top)
stack.add(newTop)
}
"C" -> stack.removeAt(stack.size - 1)
"D" -> stack.add(2 * stack.last())
else -> stack.add(op.toInt())
}
}
return stack.sum()
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 368. Largest Divisible Subset
Сложность: medium
Дан набор различных положительных целых чисел nums. Вернуть наибольшее подмножество answer, такое что каждая пара (answer[i], answer[j]) элементов в этом подмножестве удовлетворяет условию:
answer[i] % answer[j] == 0, или
answer[j] % answer[i] == 0
Если существует несколько решений, вернуть любое из них.
Пример:
👨💻 Алгоритм:
1⃣ Если число 8 может быть разделено на элемент X_i, то добавив число 8 к EDS(X_i), мы получим еще одно делимое подмножество, которое заканчивается на 8, согласно нашему следствию I. И это новое подмножество является потенциальным значением для EDS(8). Например, поскольку 8 % 2 == 0, то {2,8} может быть конечным значением для EDS(8), и аналогично для подмножества {2,4,8}, полученного из EDS(4).
2⃣ Если число 8 не может быть разделено на элемент X_i, то можно быть уверенным, что значение EDS(X_i) не повлияет на EDS(8), согласно определению делимого подмножества. Например, подмножество EDS(7)={7} не имеет влияния на EDS(8).
3⃣ Затем мы выбираем наибольшие новые подмножества, которые мы формируем с помощью EDS(X_i). В частности, подмножество {8} является допустимым кандидатом для EDS(8). И в гипотетическом случае, когда 8 не может быть разделено ни на один из предыдущих элементов, мы бы имели EDS(8)={8}.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан набор различных положительных целых чисел nums. Вернуть наибольшее подмножество answer, такое что каждая пара (answer[i], answer[j]) элементов в этом подмножестве удовлетворяет условию:
answer[i] % answer[j] == 0, или
answer[j] % answer[i] == 0
Если существует несколько решений, вернуть любое из них.
Пример:
Input: nums = [1,2,3]
Output: [1,2]
Explanation: [1,3] is also accepted.
class Solution {
fun largestDivisibleSubset(nums: IntArray): List<Int> {
val n = nums.size
if (n == 0) return listOf()
nums.sort()
val EDS = Array(n) { mutableListOf<Int>() }
for (i in 0 until n) {
var maxSubset = mutableListOf<Int>()
for (k in 0 until i) {
if (nums[i] % nums[k] == 0 && maxSubset.size < EDS[k].size) {
maxSubset = EDS[k]
}
}
EDS[i] = ArrayList(maxSubset)
EDS[i].add(nums[i])
}
var ret = mutableListOf<Int>()
for (subset in EDS) {
if (ret.size < subset.size) {
ret = subset
}
}
return ret
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1232. Check If It Is a Straight Line
Сложность: easy
Вам дан массив координат, coordinates[i] = [x, y], где [x, y] - координаты точки. Проверьте, образуют ли эти точки прямую линию в плоскости XY.
Пример:
👨💻 Алгоритм:
1⃣ Определение наклона:
Вычисляем наклон между первыми двумя точками и используем его как эталон.
2⃣ Проверка других точек:
Для всех остальных точек проверяем, совпадает ли наклон, образуемый этими точками с первой точкой, с эталонным наклоном.
3⃣ Если все наклоны совпадают, то все точки лежат на одной прямой.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Вам дан массив координат, coordinates[i] = [x, y], где [x, y] - координаты точки. Проверьте, образуют ли эти точки прямую линию в плоскости XY.
Пример:
Input: coordinates = [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7]]
Output: true
Вычисляем наклон между первыми двумя точками и используем его как эталон.
Для всех остальных точек проверяем, совпадает ли наклон, образуемый этими точками с первой точкой, с эталонным наклоном.
class Solution {
fun checkStraightLine(coordinates: Array<IntArray>): Boolean {
val (x0, y0) = coordinates[0]
val (x1, y1) = coordinates[1]
for ((x, y) in coordinates) {
if ((x1 - x0) * (y - y0) != (y1 - y0) * (x - x0)) {
return false
}
}
return true
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1498. Number of Subsequences That Satisfy the Given Sum Condition
Сложность: medium
Вам дан массив целых чисел
Верните количество непустых подпоследовательностей массива
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и подготовка:
Инициализируйте переменные answer равным 0 и n как длину массива nums.
Отсортируйте массив nums.
Подготовьте массив power для хранения степеней двойки до n по модулю 10^9+7.
2⃣ Итерация и бинарный поиск:
Для каждого индекса left от 0 до n - 1 выполните бинарный поиск, чтобы найти самый правый индекс right, где nums[right] <= target - nums[left].
Если left <= right, добавьте количество допустимых подпоследовательностей к answer.
3⃣ Возврат результата:
Верните answer по модулю 10^9+7.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан массив целых чисел
nums и целое число target.Верните количество непустых подпоследовательностей массива
nums, таких что сумма минимального и максимального элемента в них меньше или равна target. Так как ответ может быть слишком большим, верните его по модулю 10^9 + 7.Пример:
Input: nums = [3,5,6,7], target = 9
Output: 4
Explanation: There are 4 subsequences that satisfy the condition.
[3] -> Min value + max value <= target (3 + 3 <= 9)
[3,5] -> (3 + 5 <= 9)
[3,5,6] -> (3 + 6 <= 9)
[3,6] -> (3 + 6 <= 9)
Инициализируйте переменные answer равным 0 и n как длину массива nums.
Отсортируйте массив nums.
Подготовьте массив power для хранения степеней двойки до n по модулю 10^9+7.
Для каждого индекса left от 0 до n - 1 выполните бинарный поиск, чтобы найти самый правый индекс right, где nums[right] <= target - nums[left].
Если left <= right, добавьте количество допустимых подпоследовательностей к answer.
Верните answer по модулю 10^9+7.
class Solution {
fun numSubseq(nums: IntArray, target: Int): Int {
val mod = 1_000_000_007
val n = nums.size
nums.sort()
val power = IntArray(n) { 1 }
for (i in 1 until n) {
power[i] = (power[i - 1] * 2) % mod
}
var answer = 0
var left = 0
var right = n - 1
while (left <= right) {
if (nums[left] + nums[right] <= target) {
answer = (answer + power[right - left]) % mod
left++
} else {
right--
}
}
return answer
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM