Задача: 946. Validate Stack Sequences
Сложность: medium
Учитывая, что два целочисленных массива pushed и popped имеют разные значения, верните true, если это могло быть результатом последовательности операций push и pop на изначально пустом стеке, или false в противном случае.
Пример:
👨💻 Алгоритм:
1⃣ Инициализировать пустой стек.
Использовать указатель j для отслеживания текущей позиции в массиве popped.
2⃣ Пройти по каждому элементу в массиве pushed:
Добавить элемент в стек.
Проверить верхний элемент стека:
Если он совпадает с текущим элементом в popped, удалить элемент из стека и увеличить указатель j.
3⃣ В конце вернуть true, если указатель j достиг конца массива popped, иначе вернуть false.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Учитывая, что два целочисленных массива pushed и popped имеют разные значения, верните true, если это могло быть результатом последовательности операций push и pop на изначально пустом стеке, или false в противном случае.
Пример:
Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
Output: true
Использовать указатель j для отслеживания текущей позиции в массиве popped.
Добавить элемент в стек.
Проверить верхний элемент стека:
Если он совпадает с текущим элементом в popped, удалить элемент из стека и увеличить указатель j.
class Solution {
fun validateStackSequences(pushed: IntArray, popped: IntArray): Boolean {
val stack = mutableListOf<Int>()
var j = 0
for (x in pushed) {
stack.add(x)
while (stack.isNotEmpty() && j < popped.size && stack.last() == popped[j]) {
stack.removeAt(stack.size - 1)
j++
}
}
return j == popped.size
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 667. Beautiful Arrangement II
Сложность: medium
Даны два целых числа n и k, составьте список answer, содержащий n различных положительных чисел в диапазоне от 1 до n, который соответствует следующему требованию:
Предположим, что этот список answer = [a1, a2, a3, ... , an], тогда список [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] имеет ровно k различных чисел. Верните список answer. Если существует несколько допустимых ответов, верните любой из них.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация списка:
Начните с создания списка от 1 до n: [1, 2, 3, ..., n].
2⃣ Конструирование шаблона с k различиями:
Для обеспечения k различных значений разностей используйте следующий подход:
Включайте числа попеременно с конца и начала списка, начиная с n и 1, чтобы создать как можно больше уникальных разностей.
Если требуется меньше k, оставшиеся числа просто добавляйте в порядке возрастания, чтобы не увеличивать количество уникальных разностей.
3⃣ Заполнение списка:
Заполните оставшуюся часть списка последовательными числами, чтобы сохранить уникальные числа в диапазоне от 1 до n.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Даны два целых числа n и k, составьте список answer, содержащий n различных положительных чисел в диапазоне от 1 до n, который соответствует следующему требованию:
Предположим, что этот список answer = [a1, a2, a3, ... , an], тогда список [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] имеет ровно k различных чисел. Верните список answer. Если существует несколько допустимых ответов, верните любой из них.
Пример:
Input: n = 3, k = 1
Output: [1,2,3]
Explanation: The [1,2,3] has three different positive integers ranging from 1 to 3, and the [1,1] has exactly 1 distinct integer: 1
Начните с создания списка от 1 до n: [1, 2, 3, ..., n].
Для обеспечения k различных значений разностей используйте следующий подход:
Включайте числа попеременно с конца и начала списка, начиная с n и 1, чтобы создать как можно больше уникальных разностей.
Если требуется меньше k, оставшиеся числа просто добавляйте в порядке возрастания, чтобы не увеличивать количество уникальных разностей.
Заполните оставшуюся часть списка последовательными числами, чтобы сохранить уникальные числа в диапазоне от 1 до n.
fun constructArray(n: Int, k: Int): IntArray {
val answer = mutableListOf<Int>()
var left = 1
var right = n
for (i in 0..k) {
if (i % 2 == 0) {
answer.add(left)
left++
} else {
answer.add(right)
right--
}
}
if (k % 2 == 0) {
for (i in left..right) answer.add(i)
} else {
for (i in right downTo left) answer.add(i)
}
return answer.toIntArray()
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 665. Non-decreasing Array
Сложность: medium
Дан массив nums из n целых чисел. Ваша задача - проверить, можно ли сделать его неубывающим, изменив не более одного элемента.
Мы определяем массив как неубывающий, если для каждого i (индексация с 0), такого что 0 <= i <= n - 2, выполняется условие nums[i] <= nums[i + 1].
Пример:
👨💻 Алгоритм:
1⃣ Инициализация переменных:
Завести переменную count для подсчета числа изменений.
Проверить последовательность чисел в массиве nums.
2⃣ Проверка условий:
Если nums[i] > nums[i + 1], то увеличиваем count.
Если count превышает 1, возвращаем false, так как больше одного изменения недопустимо.
Если nums[i - 1] > nums[i + 1] и nums[i] > nums[i + 2], то возвращаем false.
3⃣ Возврат результата:
Если количество изменений не превышает 1, вернуть true.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив nums из n целых чисел. Ваша задача - проверить, можно ли сделать его неубывающим, изменив не более одного элемента.
Мы определяем массив как неубывающий, если для каждого i (индексация с 0), такого что 0 <= i <= n - 2, выполняется условие nums[i] <= nums[i + 1].
Пример:
Input: nums = [4,2,3]
Output: true
Explanation: You could modify the first 4 to 1 to get a non-decreasing array.
Завести переменную count для подсчета числа изменений.
Проверить последовательность чисел в массиве nums.
Если nums[i] > nums[i + 1], то увеличиваем count.
Если count превышает 1, возвращаем false, так как больше одного изменения недопустимо.
Если nums[i - 1] > nums[i + 1] и nums[i] > nums[i + 2], то возвращаем false.
Если количество изменений не превышает 1, вернуть true.
class Solution {
fun checkPossibility(nums: IntArray): Boolean {
var count = 0
for (i in 1 until nums.size) {
if (nums[i] < nums[i - 1]) {
if (count > 0) {
return false
}
count++
if (i == 1 || nums[i] >= nums[i - 2]) {
nums[i - 1] = nums[i]
} else {
nums[i] = nums[i - 1]
}
}
}
return true
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 189. Rotate Array
Сложность: medium
Для целочисленного массива nums, поверните массив вправо на k шагов, где k — неотрицательное число.
Пример:
👨💻 Алгоритм:
1⃣ Создаем дополнительный массив, в который будем помещать каждый элемент исходного массива на его новую позицию. Элемент на позиции i в исходном массиве будет размещен на индексе (i+k) % длина массива.
2⃣ Копируем элементы из нового массива в исходный массив, сохраняя новый порядок элементов.
3⃣ Заменяем исходный массив полученным результатом, завершая процесс поворота массива.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Для целочисленного массива nums, поверните массив вправо на k шагов, где k — неотрицательное число.
Пример:
Input: nums = [1,2,3,4,5,6,7], k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
class Solution {
fun rotate(nums: IntArray, k: Int) {
val n = nums.size
val a = IntArray(n)
for (i in nums.indices) {
a[(i + k) % n] = nums[i]
}
for (i in nums.indices) {
nums[i] = a[i]
}
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 922. Sort Array By Parity II
Сложность: medium
Дан массив целых чисел nums, половина целых чисел в нем нечетные, а другая половина - четные. Отсортируйте массив так, чтобы во всех случаях, когда nums[i] нечетный, i был нечетным, а во всех случаях, когда nums[i] четный, i был четным. Верните любой массив ответов, удовлетворяющий этому условию.
Пример:
👨💻 Алгоритм:
1⃣ Инициализировать два указателя even_idx и odd_idx для отслеживания позиций четных и нечетных индексов соответственно.
2⃣ Пройти по массиву nums и для каждого элемента:
Если элемент четный, поместить его на позицию even_idx и увеличить even_idx на 2.
Если элемент нечетный, поместить его на позицию odd_idx и увеличить odd_idx на 2.
3⃣ Вернуть отсортированный массив.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив целых чисел nums, половина целых чисел в нем нечетные, а другая половина - четные. Отсортируйте массив так, чтобы во всех случаях, когда nums[i] нечетный, i был нечетным, а во всех случаях, когда nums[i] четный, i был четным. Верните любой массив ответов, удовлетворяющий этому условию.
Пример:
Input: nums = [4,2,5,7]
Output: [4,5,2,7]
Если элемент четный, поместить его на позицию even_idx и увеличить even_idx на 2.
Если элемент нечетный, поместить его на позицию odd_idx и увеличить odd_idx на 2.
class Solution {
fun sortArrayByParityII(nums: IntArray): IntArray {
val result = IntArray(nums.size)
var evenIdx = 0
var oddIdx = 1
for (num in nums) {
if (num % 2 == 0) {
result[evenIdx] = num
evenIdx += 2
} else {
result[oddIdx] = num
oddIdx += 2
}
}
return result
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 724. Find Pivot Index
Сложность: easy
Если задан массив целых чисел nums, вычислите поворотный индекс этого массива. Поворотный индекс - это индекс, при котором сумма всех чисел строго слева от индекса равна сумме всех чисел строго справа от индекса. Если индекс находится на левом краю массива, то сумма слева равна 0, так как слева нет элементов. Это относится и к правому краю массива. Возвращается самый левый поворотный индекс. Если такого индекса не существует, возвращается -1.
Пример:
👨💻 Алгоритм:
1⃣ Вычислите сумму всех элементов массива.
2⃣ Пройдите по массиву, вычисляя текущую сумму элементов слева и проверяя, равна ли она разности между общей суммой и текущей суммой справа.
3⃣ Если текущий индекс удовлетворяет условию, верните его; если нет, продолжайте проверку. Если такой индекс не найден, верните -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Если задан массив целых чисел nums, вычислите поворотный индекс этого массива. Поворотный индекс - это индекс, при котором сумма всех чисел строго слева от индекса равна сумме всех чисел строго справа от индекса. Если индекс находится на левом краю массива, то сумма слева равна 0, так как слева нет элементов. Это относится и к правому краю массива. Возвращается самый левый поворотный индекс. Если такого индекса не существует, возвращается -1.
Пример:
Input: nums = [1,7,3,6,5,6]
Output: 3
fun pivotIndex(nums: IntArray): Int {
val totalSum = nums.sum()
var leftSum = 0
for (i in nums.indices) {
if (leftSum == totalSum - leftSum - nums[i]) {
return i
}
leftSum += nums[i]
}
return -1
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 757. Set Intersection Size At Least Two
Сложность: hard
Вам дан двумерный целочисленный массив intervals, в котором intervals[i] = [starti, endi] представляет все целые числа от starti до endi включительно. Содержащее множество - это массив nums, в котором каждый интервал из intervals содержит не менее двух целых чисел в nums. Например, если intervals = [[1,3], [3,7], [8,9]], то [1,2,4,7,8,9] и [2,3,4,8,9] - содержащие множества. Верните минимально возможный размер содержащего множества.
Пример:
👨💻 Алгоритм:
1⃣ Отсортируйте интервалы по их конечным точкам.
2⃣ Инициализируйте пустое множество для хранения чисел.
3⃣ Пройдите по каждому интервалу, добавляя необходимые числа в множество так, чтобы каждый интервал содержал не менее двух чисел из этого множества.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Вам дан двумерный целочисленный массив intervals, в котором intervals[i] = [starti, endi] представляет все целые числа от starti до endi включительно. Содержащее множество - это массив nums, в котором каждый интервал из intervals содержит не менее двух целых чисел в nums. Например, если intervals = [[1,3], [3,7], [8,9]], то [1,2,4,7,8,9] и [2,3,4,8,9] - содержащие множества. Верните минимально возможный размер содержащего множества.
Пример:
Input: intervals = [[1,3],[3,7],[8,9]]
Output: 5
fun minSetSize(intervals: Array<IntArray>): Int {
intervals.sortBy { it[1] }
val nums = mutableListOf<Int>()
for (interval in intervals) {
val start = interval[0]
val end = interval[1]
if (nums.isEmpty() || nums.last() < start) {
nums.add(end - 1)
nums.add(end)
} else if (nums.last() == end - 1) {
nums.add(end)
}
}
return nums.size
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 120. Triangle
Сложность: medium
Дан массив в виде треугольника, верните минимальную сумму пути сверху вниз.
На каждом шаге вы можете перейти к соседнему числу в строке ниже. Более формально, если вы находитесь на индексе i в текущей строке, вы можете перейти либо к индексу i, либо к индексу i + 1 в следующей строке.
Пример:
👨💻 Алгоритм:
1⃣ Простейший способ реализации этого заключается в перезаписи входных данных, то есть в использовании алгоритма "на месте". В подходе 2 мы рассмотрим, как модифицировать алгоритм так, чтобы он не перезаписывал входные данные, но при этом не требовал более чем O(n) дополнительного пространства.
2⃣ Когда этот алгоритм завершит свою работу, каждая ячейка (строка, столбец) входного треугольника будет перезаписана минимальной суммой пути от (0, 0) (вершины треугольника) до (строка, столбец) включительно.
Совет на собеседовании: Алгоритмы "на месте" перезаписывают входные данные для экономии места, но иногда это может вызвать проблемы. Вот несколько ситуаций, когда алгоритм "на месте" может быть неуместен.
3⃣ 1. Алгоритму необходимо работать в многопоточной среде, без эксклюзивного доступа к массиву. Другим потокам может потребоваться читать массив тоже, и они могут не ожидать, что он будет изменен.
2. Даже если поток один, или у алгоритма есть эксклюзивный доступ к массиву во время выполнения, массив может потребоваться повторно использовать позже или другим потоком после освобождения блокировки.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив в виде треугольника, верните минимальную сумму пути сверху вниз.
На каждом шаге вы можете перейти к соседнему числу в строке ниже. Более формально, если вы находитесь на индексе i в текущей строке, вы можете перейти либо к индексу i, либо к индексу i + 1 в следующей строке.
Пример:
Input: triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
Output: 11
Explanation: The triangle looks like:
2
3 4
6 5 7
4 1 8 3
The minimum path sum from top to bottom is 2 + 3 + 5 + 1 = 11 (underlined above).
Совет на собеседовании: Алгоритмы "на месте" перезаписывают входные данные для экономии места, но иногда это может вызвать проблемы. Вот несколько ситуаций, когда алгоритм "на месте" может быть неуместен.
2. Даже если поток один, или у алгоритма есть эксклюзивный доступ к массиву во время выполнения, массив может потребоваться повторно использовать позже или другим потоком после освобождения блокировки.
class Solution {
fun minimumTotal(triangle: MutableList<MutableList<Int>>): Int {
for (row in 1 until triangle.size) {
for (col in 0..row) {
var smallestAbove = Int.MAX_VALUE
if (col > 0) {
smallestAbove = triangle[row - 1][col - 1]
}
if (col < row) {
smallestAbove = minOf(smallestAbove, triangle[row - 1][col])
}
triangle[row][col] += smallestAbove
}
}
return triangle.last().minOrNull() ?: Int.MAX_VALUE
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 285. Inorder Successor in BST
Сложность: medium
Дан корень бинарного дерева поиска и узел p в нем. Верните преемника этого узла в порядке возрастания в бинарном дереве поиска (BST). Если у данного узла нет преемника в порядке возрастания в дереве, верните null.
Преемник узла p — это узел с наименьшим ключом, который больше p.val.
Пример:
👨💻 Алгоритм:
1⃣ Определение переменных класса:
Определите две переменные класса: previous и inorderSuccessorNode. Переменная previous будет использоваться при обработке второго случая, а inorderSuccessorNode будет содержать результат, который нужно вернуть.
2⃣ Обработка двух случаев:
В функции inorderSuccessor сначала проверьте, какой из двух случаев нужно обработать, проверяя наличие правого дочернего элемента.
Правый дочерний элемент существует:
- присвойте правый дочерний элемент узлу leftmost и итерируйтесь, пока не достигнете узла (leftmost), у которого нет левого дочернего элемента. Итерируйте, присваивая leftmost = leftmost.left, пока не получите левый узел в поддереве.
Правый дочерний элемент не существует:
- определите функцию inorderCase2 и передайте ей узел и узел p.
- выполните простой обход в порядке возрастания: сначала рекурсируйте на левый дочерний элемент узла.
- когда рекурсия вернется, проверьте, равна ли переменная класса previous узлу p. Если это так, значит p является предшественником узла, или, другими словами, узел является преемником узла p. Назначьте inorderSuccessorNode узлу и вернитесь из функции.
- наконец, верните inorderSuccessorNode как результат.
3⃣ Итерация и обновление:
В функции inorderCase2 обновляйте previous текущим узлом и продолжайте рекурсировать на правый дочерний элемент.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан корень бинарного дерева поиска и узел p в нем. Верните преемника этого узла в порядке возрастания в бинарном дереве поиска (BST). Если у данного узла нет преемника в порядке возрастания в дереве, верните null.
Преемник узла p — это узел с наименьшим ключом, который больше p.val.
Пример:
Input: root = [2,1,3], p = 1
Output: 2
Explanation: 1's in-order successor node is 2. Note that both p and the return value is of TreeNode type.
Определите две переменные класса: previous и inorderSuccessorNode. Переменная previous будет использоваться при обработке второго случая, а inorderSuccessorNode будет содержать результат, который нужно вернуть.
В функции inorderSuccessor сначала проверьте, какой из двух случаев нужно обработать, проверяя наличие правого дочернего элемента.
Правый дочерний элемент существует:
- присвойте правый дочерний элемент узлу leftmost и итерируйтесь, пока не достигнете узла (leftmost), у которого нет левого дочернего элемента. Итерируйте, присваивая leftmost = leftmost.left, пока не получите левый узел в поддереве.
Правый дочерний элемент не существует:
- определите функцию inorderCase2 и передайте ей узел и узел p.
- выполните простой обход в порядке возрастания: сначала рекурсируйте на левый дочерний элемент узла.
- когда рекурсия вернется, проверьте, равна ли переменная класса previous узлу p. Если это так, значит p является предшественником узла, или, другими словами, узел является преемником узла p. Назначьте inorderSuccessorNode узлу и вернитесь из функции.
- наконец, верните inorderSuccessorNode как результат.
В функции inorderCase2 обновляйте previous текущим узлом и продолжайте рекурсировать на правый дочерний элемент.
class TreeNode(var `val`: Int) {
var left: TreeNode? = null
var right: TreeNode? = null
}
class Solution {
private var previous: TreeNode? = null
private var inorderSuccessorNode: TreeNode? = null
fun inorderSuccessor(root: TreeNode?, p: TreeNode?): TreeNode? {
if (p?.right != null) {
var leftmost = p.right
while (leftmost?.left != null) {
leftmost = leftmost.left
}
inorderSuccessorNode = leftmost
} else {
inorderCase2(root, p)
}
return inorderSuccessorNode
}
private fun inorderCase2(node: TreeNode?, p: TreeNode?) {
if (node == null) {
return
}
inorderCase2(node.left, p)
if (previous == p && inorderSuccessorNode == null) {
inorderSuccessorNode = node
return
}
previous = node
inorderCase2(node.right, p)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1054. Distant Barcodes
Сложность: medium
На складе имеется ряд штрих-кодов, где i-й штрих-код - barcodes[i]. Переставьте штрих-коды так, чтобы два соседних штрих-кода не были одинаковыми. Вы можете вернуть любой ответ, и гарантируется, что ответ существует.
Пример:
👨💻 Алгоритм:
1⃣ Подсчитай частоту каждого штрих-кода.
Помести все штрих-коды в максимальную кучу на основе их частоты.
2⃣ Извлекай штрих-коды из кучи, чередуя их, чтобы два соседних штрих-кода не были одинаковыми.
3⃣ Если куча становится пустой, помести временно сохранённый штрих-код обратно в кучу.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
На складе имеется ряд штрих-кодов, где i-й штрих-код - barcodes[i]. Переставьте штрих-коды так, чтобы два соседних штрих-кода не были одинаковыми. Вы можете вернуть любой ответ, и гарантируется, что ответ существует.
Пример:
Input: barcodes = [1,1,1,2,2,2]
Output: [2,1,2,1,2,1]
Помести все штрих-коды в максимальную кучу на основе их частоты.
fun rearrangeBarcodes(barcodes: IntArray): IntArray {
val count = barcodes.groupingBy { it }.eachCount().toMutableMap()
val maxHeap = PriorityQueue(compareByDescending<Pair<Int, Int>> { it.first }.thenBy { it.second })
count.forEach { (barcode, freq) -> maxHeap.add(Pair(freq, barcode)) }
val result = mutableListOf<Int>()
var prevFreq = 0
var prevBarcode = 0
while (maxHeap.isNotEmpty()) {
val (freq, barcode) = maxHeap.poll()
result.add(barcode)
if (prevFreq > 0) {
maxHeap.add(Pair(prevFreq, prevBarcode))
}
prevFreq = freq - 1
prevBarcode = barcode
}
return result.toIntArray()
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1402. Reducing Dishes
Сложность: hard
Шеф-повар собрал данные об уровне удовлетворенности от своих n блюд. Шеф может приготовить любое блюдо за 1 единицу времени.
Коэффициент удовольствия от блюда определяется как время, затраченное на приготовление этого блюда вместе с предыдущими блюдами, умноженное на уровень удовлетворенности от этого блюда, то есть time[i] * satisfaction[i].
Верните максимальную сумму коэффициентов удовольствия, которую шеф-повар может получить после приготовления некоторого количества блюд.
Блюда можно готовить в любом порядке, и шеф может отказаться от некоторых блюд, чтобы достичь максимального значения.
Пример:
👨💻 Алгоритм:
1⃣ Отсортируйте массив satisfaction в порядке возрастания.
2⃣ Создайте таблицу мемоизации memo размером N x N и инициализируйте все значения -1, что будет означать, что ответ для всех состояний еще не рассчитан.
3⃣ Реализуйте функцию, которая вызывается с параметрами index = 0 и time = 1, чтобы найти ответ:
Если достигнут конец массива, т.е. index == satisfaction.length, верните 0, так как больше нет блюд для приготовления и нельзя получить дополнительное значение.
Если значение в массиве memo для пары {index, time} не равно -1, верните это значение, так как это подразумевает, что данная подзадача уже была решена; поэтому рекурсивный вызов не требуется, и можно вернуть сохраненное значение из таблицы memo.
Рассчитайте максимум из двух вариантов:
- добавьте значение коэффициента для данного блюда satisfaction[index] * time к рекурсивному результату с index = index + 1 и time = time + 1.
- пропустите текущее блюдо и сделайте рекурсивный вызов для index = index + 1 и time = time.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Шеф-повар собрал данные об уровне удовлетворенности от своих n блюд. Шеф может приготовить любое блюдо за 1 единицу времени.
Коэффициент удовольствия от блюда определяется как время, затраченное на приготовление этого блюда вместе с предыдущими блюдами, умноженное на уровень удовлетворенности от этого блюда, то есть time[i] * satisfaction[i].
Верните максимальную сумму коэффициентов удовольствия, которую шеф-повар может получить после приготовления некоторого количества блюд.
Блюда можно готовить в любом порядке, и шеф может отказаться от некоторых блюд, чтобы достичь максимального значения.
Пример:
Input: satisfaction = [-1,-8,0,5,-9]
Output: 14
Explanation: After Removing the second and last dish, the maximum total like-time coefficient will be equal to (-1*1 + 0*2 + 5*3 = 14).
Each dish is prepared in one unit of time.
Если достигнут конец массива, т.е. index == satisfaction.length, верните 0, так как больше нет блюд для приготовления и нельзя получить дополнительное значение.
Если значение в массиве memo для пары {index, time} не равно -1, верните это значение, так как это подразумевает, что данная подзадача уже была решена; поэтому рекурсивный вызов не требуется, и можно вернуть сохраненное значение из таблицы memo.
Рассчитайте максимум из двух вариантов:
- добавьте значение коэффициента для данного блюда satisfaction[index] * time к рекурсивному результату с index = index + 1 и time = time + 1.
- пропустите текущее блюдо и сделайте рекурсивный вызов для index = index + 1 и time = time.
class Solution {
fun maxSatisfaction(satisfaction: IntArray): Int {
satisfaction.sort()
val memo = Array(satisfaction.size + 1) { IntArray(satisfaction.size + 1) { -1 } }
fun findMaxSatisfaction(satisfaction: IntArray, memo: Array<IntArray>, index: Int, time: Int): Int {
if (index == satisfaction.size) return 0
if (memo[index][time] != -1) return memo[index][time]
memo[index][time] = maxOf(satisfaction[index] * time + findMaxSatisfaction(satisfaction, memo, index + 1, time + 1),
findMaxSatisfaction(satisfaction, memo, index + 1, time))
return memo[index][time]
}
return findMaxSatisfaction(satisfaction, memo, 0, 1)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 955. Delete Columns to Make Sorted II
Сложность: medium
Вам дан массив из n строк одинаковой длины. Мы можем выбрать любые индексы удаления и удалить все символы в этих индексах для каждой строки.
Например, если у нас есть strs = ["abcdef", "uvwxyz"] и индексы удаления {0, 2, 3}, то конечный массив после удаления будет ["bef", "vyz"]. Предположим, что мы выбрали набор индексов удаления answer таким образом, что после удаления конечный массив имеет элементы в лексикографическом порядке (т.е, strs[0] <= strs[1] <= strs[2] <= ... <= strs[n - 1]). Возвращает минимально возможное значение answer.length.
Пример:
👨💻 Алгоритм:
1⃣ Определить количество строк n и длину каждой строки m.
Создать массив delete_count длиной m, который будет отслеживать количество удаляемых столбцов.
2⃣ Итеративно проверить каждую пару соседних строк для всех столбцов.
Если для данной пары строк обнаружено нарушение лексикографического порядка, отметить соответствующий столбец для удаления.
3⃣ Повторять процесс до тех пор, пока массив строк не станет лексикографически отсортированным.
Вернуть количество удаленных столбцов.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дан массив из n строк одинаковой длины. Мы можем выбрать любые индексы удаления и удалить все символы в этих индексах для каждой строки.
Например, если у нас есть strs = ["abcdef", "uvwxyz"] и индексы удаления {0, 2, 3}, то конечный массив после удаления будет ["bef", "vyz"]. Предположим, что мы выбрали набор индексов удаления answer таким образом, что после удаления конечный массив имеет элементы в лексикографическом порядке (т.е, strs[0] <= strs[1] <= strs[2] <= ... <= strs[n - 1]). Возвращает минимально возможное значение answer.length.
Пример:
Input: strs = ["ca","bb","ac"]
Output: 1
Создать массив delete_count длиной m, который будет отслеживать количество удаляемых столбцов.
Если для данной пары строк обнаружено нарушение лексикографического порядка, отметить соответствующий столбец для удаления.
Вернуть количество удаленных столбцов.
class Solution {
fun minDeletionSize(strs: Array<String>): Int {
val n = strs.size
val m = strs[0].length
val deleteCount = BooleanArray(m)
fun isSorted(): Boolean {
for (i in 0 until n - 1) {
for (j in 0 until m) {
if (deleteCount[j]) continue
if (strs[i][j] > strs[i + 1][j]) return false
if (strs[i][j] < strs[i + 1][j]) break
}
}
return true
}
while (!isSorted()) {
for (j in 0 until m) {
if (deleteCount[j]) continue
for (i in 0 until n - 1) {
if (strs[i][j] > strs[i + 1][j]) {
deleteCount[j] = true
break
}
}
if (deleteCount[j]) break
}
}
return deleteCount.count { it }
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 238. Product of Array Except Self
Сложность: medium
Дан массив целых чисел nums, верните массив answer такой, что answer[i] равен произведению всех элементов массива nums, кроме nums[i].
Произведение любого префикса или суффикса массива nums гарантированно помещается в 32-битное целое число.
Вы должны написать алгоритм, который работает за время O(n) и не использует операцию деления.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация массивов L и R: Инициализируйте два пустых массива L и R. Массив L будет содержать произведение всех чисел слева от i, а массив R будет содержать произведение всех чисел справа от i. Заполните массив L, установив L[0] равным 1, а для остальных элементов используйте формулу L[i] = L[i-1] * nums[i-1]. Заполните массив R, установив R[length-1] равным 1, а для остальных элементов используйте формулу R[i] = R[i+1] * nums[i+1].
2⃣ Заполнение массивов L и R: Пройдите два цикла для заполнения массивов L и R. В первом цикле заполните массив L, начиная с L[0] и двигаясь вправо. Во втором цикле заполните массив R, начиная с R[length-1] и двигаясь влево.
3⃣ Формирование результата: Пройдите по исходному массиву и для каждого элемента i вычислите произведение всех элементов, кроме nums[i], используя L[i] * R[i]. Сохраните результат в массиве answer и верните его.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив целых чисел nums, верните массив answer такой, что answer[i] равен произведению всех элементов массива nums, кроме nums[i].
Произведение любого префикса или суффикса массива nums гарантированно помещается в 32-битное целое число.
Вы должны написать алгоритм, который работает за время O(n) и не использует операцию деления.
Пример:
Input: nums = [1,2,3,4]
Output: [24,12,8,6]
class Solution {
fun productExceptSelf(nums: IntArray): IntArray {
val length = nums.size
val L = IntArray(length) { 1 }
val R = IntArray(length) { 1 }
val answer = IntArray(length) { 1 }
for (i in 1 until length) {
L[i] = nums[i - 1] * L[i - 1]
}
for (i in length - 2 downTo 0) {
R[i] = nums[i + 1] * R[i + 1]
}
for (i in 0 until length) {
answer[i] = L[i] * R[i]
}
return answer
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 408. Valid Word Abbreviation
Сложность: easy
Строку можно сократить, заменив любое количество не смежных, непустых подстрок их длинами. Длины не должны содержать ведущих нулей.
Например, строка "замена" может быть сокращена следующим образом (но не ограничивается этим): "s10n" ("s ubstitutio n") "sub4u4" ("sub stit u tion") "12" ("замена") "su3i1u2on" ("su bst i t u ti on") "substitution" (без замены подстрок) Следующие сокращения не являются допустимыми:
"s55n" ("s ubsti tutio n", заменяемые подстроки смежные) "s010n" (содержит ведущие нули) "s0ubstitution" (заменяет пустую подстроку) Если задано строковое слово и аббревиатура abbr, верните, соответствует ли строка заданной аббревиатуре.
Подстрока - это непрерывная непустая последовательность символов в строке.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте два указателя: один для строки word и один для аббревиатуры abbr. Начните сравнение символов строки и аббревиатуры с начала.
2⃣ Если символ аббревиатуры - это цифра, вычислите полное число и переместите указатель строки word на это количество символов. Если символ аббревиатуры - это буква, убедитесь, что он совпадает с текущим символом строки.
3⃣ Повторяйте шаг 2, пока оба указателя не достигнут конца строки и аббревиатуры соответственно. Если это так, верните true, иначе false.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Строку можно сократить, заменив любое количество не смежных, непустых подстрок их длинами. Длины не должны содержать ведущих нулей.
Например, строка "замена" может быть сокращена следующим образом (но не ограничивается этим): "s10n" ("s ubstitutio n") "sub4u4" ("sub stit u tion") "12" ("замена") "su3i1u2on" ("su bst i t u ti on") "substitution" (без замены подстрок) Следующие сокращения не являются допустимыми:
"s55n" ("s ubsti tutio n", заменяемые подстроки смежные) "s010n" (содержит ведущие нули) "s0ubstitution" (заменяет пустую подстроку) Если задано строковое слово и аббревиатура abbr, верните, соответствует ли строка заданной аббревиатуре.
Подстрока - это непрерывная непустая последовательность символов в строке.
Пример:
Input: word = "internationalization", abbr = "i12iz4n"
Output: true
fun validWordAbbreviation(word: String, abbr: String): Boolean {
var i = 0
var j = 0
while (i < word.length && j < abbr.length) {
if (abbr[j].isDigit()) {
if (abbr[j] == '0') {
return false
}
var num = 0
while (j < abbr.length && abbr[j].isDigit()) {
num = num * 10 + (abbr[j] - '0')
j++
}
i += num
} else {
if (word[i] != abbr[j]) {
return false
}
i++
j++
}
}
return i == word.length && j == abbr.length
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 443. String Compression
Сложность: medium
Дан массив символов chars, сжать его, используя следующий алгоритм:
Начните с пустой строки s. Для каждой группы последовательных повторяющихся символов в chars:
Если длина группы равна 1, добавьте символ к строке s.
В противном случае добавьте символ, а за ним длину группы.
Сжатая строка s не должна возвращаться отдельно, а вместо этого должна быть сохранена в входном массиве символов chars. Обратите внимание, что длины групп, которые равны 10 или более, будут разделены на несколько символов в chars.
После того как вы закончите модификацию входного массива, верните новую длину массива.
Вы должны написать алгоритм, который использует только постоянное дополнительное пространство.
Пример:
👨💻 Алгоритм:
1⃣ Объявите переменные i – первый индекс текущей группы, и res – длина ответа (сжатой строки). Инициализируйте i = 0, res = 0.
2⃣ Пока i меньше длины chars: Найдите длину текущей группы последовательных повторяющихся символов groupLength. Добавьте chars[i] к ответу (chars[res++] = chars[i]). Если groupLength > 1, добавьте строковое представление groupLength к ответу и увеличьте res соответственно. Увеличьте i на groupLength и перейдите к следующей группе.
3⃣ Верните res.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив символов chars, сжать его, используя следующий алгоритм:
Начните с пустой строки s. Для каждой группы последовательных повторяющихся символов в chars:
Если длина группы равна 1, добавьте символ к строке s.
В противном случае добавьте символ, а за ним длину группы.
Сжатая строка s не должна возвращаться отдельно, а вместо этого должна быть сохранена в входном массиве символов chars. Обратите внимание, что длины групп, которые равны 10 или более, будут разделены на несколько символов в chars.
После того как вы закончите модификацию входного массива, верните новую длину массива.
Вы должны написать алгоритм, который использует только постоянное дополнительное пространство.
Пример:
Input: chars = ["a","a","b","b","c","c","c"]
Output: Return 6, and the first 6 characters of the input array should be: ["a","2","b","2","c","3"]
Explanation: The groups are "aa", "bb", and "ccc". This compresses to "a2b2c3".
class Solution {
fun compress(chars: CharArray): Int {
var i = 0
var res = 0
while (i < chars.size) {
var groupLength = 1
while (i + groupLength < chars.size && chars[i + groupLength] == chars[i]) {
groupLength++
}
chars[res] = chars[i]
res++
if (groupLength > 1) {
val strRepr = groupLength.toString()
for (ch in strRepr) {
chars[res] = ch
res++
}
}
i += groupLength
}
return res
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 486. Predict the Winner
Сложность: Medium
Дан целочисленный массив nums. Два игрока играют в игру с этим массивом: игрок 1 и игрок 2.
Игрок 1 и игрок 2 ходят по очереди, начиная с игрока 1. Оба игрока начинают игру с нулевым счетом. В каждый ход игрок берет одно из чисел с любого конца массива (то есть nums[0] или nums[nums.length - 1]), что уменьшает размер массива на 1. Игрок добавляет выбранное число к своему счету. Игра заканчивается, когда в массиве не останется элементов.
Верните true, если игрок 1 может выиграть игру. Если счета обоих игроков равны, игрок 1 все равно считается победителем, и вы также должны вернуть true. Вы можете считать, что оба игрока играют оптимально.
Пример:
👨💻 Алгоритм:
1⃣ Определите maxDiff(left, right) как максимальную разницу в счете, которую текущий игрок может достичь. Если left = right, верните nums[left].
2⃣ В противном случае текущий игрок может выбрать nums[left] или nums[right]. Максимальная разница в счете, которую он может получить, равна большему из значений nums[left] - maxDiff(left + 1, right) и nums[right] - maxDiff(left, right - 1).
3⃣ Верните true, если maxDiff(0, n - 1) >= 0. Этот вызов сделан с точки зрения первого игрока, и первый игрок является победителем, если у игроков одинаковый счет (разница 0).
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: Medium
Дан целочисленный массив nums. Два игрока играют в игру с этим массивом: игрок 1 и игрок 2.
Игрок 1 и игрок 2 ходят по очереди, начиная с игрока 1. Оба игрока начинают игру с нулевым счетом. В каждый ход игрок берет одно из чисел с любого конца массива (то есть nums[0] или nums[nums.length - 1]), что уменьшает размер массива на 1. Игрок добавляет выбранное число к своему счету. Игра заканчивается, когда в массиве не останется элементов.
Верните true, если игрок 1 может выиграть игру. Если счета обоих игроков равны, игрок 1 все равно считается победителем, и вы также должны вернуть true. Вы можете считать, что оба игрока играют оптимально.
Пример:
Input: nums = [1,5,2]
Output: false
Explanation: Initially, player 1 can choose between 1 and 2.
If he chooses 2 (or 1), then player 2 can choose from 1 (or 2) and 5. If player 2 chooses 5, then player 1 will be left with 1 (or 2).
So, final score of player 1 is 1 + 2 = 3, and player 2 is 5.
Hence, player 1 will never be the winner and you need to return
class Solution {
private fun maxDiff(nums: IntArray, left: Int, right: Int): Int {
if (left == right) {
return nums[left]
}
val scoreByLeft = nums[left] - maxDiff(nums, left + 1, right)
val scoreByRight = nums[right] - maxDiff(nums, left, right - 1)
return maxOf(scoreByLeft, scoreByRight)
}
fun predictTheWinner(nums: IntArray): Boolean {
return maxDiff(nums, 0, nums.size - 1) >= 0
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 532. K-diff Pairs in an Array
Сложность: medium
Дан массив целых чисел nums и целое число k. Верните количество уникальных пар с разницей k в массиве.
Пара с разницей k — это пара целых чисел (nums[i], nums[j]), для которой выполняются следующие условия:
0 <= i, j < nums.length
i != j
|nums[i] - nums[j]| == k
Обратите внимание, что |val| обозначает абсолютное значение val.
Пример:
👨💻 Алгоритм:
1⃣ Создайте частотный хэш-словарь для подсчета количества каждого уникального числа в массиве nums.
2⃣ Для каждого ключа в хэш-словаре проверьте, можно ли найти пару, удовлетворяющую условиям:
Если k > 0, проверьте, существует ли ключ, равный x + k.
Если k == 0, проверьте, есть ли более одного вхождения x.
3⃣ Увеличьте счётчик результатов, если условие выполняется.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив целых чисел nums и целое число k. Верните количество уникальных пар с разницей k в массиве.
Пара с разницей k — это пара целых чисел (nums[i], nums[j]), для которой выполняются следующие условия:
0 <= i, j < nums.length
i != j
|nums[i] - nums[j]| == k
Обратите внимание, что |val| обозначает абсолютное значение val.
Пример:
Input: nums = [3,1,4,1,5], k = 2
Output: 2
Explanation: There are two 2-diff pairs in the array, (1, 3) and (3, 5).
Although we have two 1s in the input, we should only return the number of unique pairs.
Если k > 0, проверьте, существует ли ключ, равный x + k.
Если k == 0, проверьте, есть ли более одного вхождения x.
class Solution {
fun findPairs(nums: IntArray, k: Int): Int {
val counter = mutableMapOf<Int, Int>()
for (num in nums) {
counter[num] = counter.getOrDefault(num, 0) + 1
}
var result = 0
for ((x, val) in counter) {
if (k > 0 && counter.containsKey(x + k)) {
result++
} else if (k == 0 && val > 1) {
result++
}
}
return result
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1039. Minimum Score Triangulation of Polygon
Сложность: medium
У вас есть выпуклый n-сторонний многоугольник, каждая вершина которого имеет целочисленное значение. Вам дан целочисленный массив values, где values[i] - это значение i-й вершины (т.е. по часовой стрелке). Вы должны триангулировать многоугольник на n - 2 треугольника. Для каждого треугольника значение этого треугольника равно произведению значений его вершин, а общий балл триангуляции равен сумме этих значений для всех n - 2 треугольников в триангуляции. Верните наименьший возможный общий балл, который вы можете получить с помощью некоторой триангуляции многоугольника.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация:
Создаем двумерный массив dp, где dp[i][j] будет хранить минимальный возможный общий балл триангуляции многоугольника, состоящего из вершин от i до j.
2⃣ Основное заполнение dp:
Проходим по всем возможным длинам подмногоугольников, начиная с треугольников (длина 3) до всего многоугольника (длина n).
Для каждого подмногоугольника находим минимальный возможный общий балл, проверяя все возможные треугольники, которые могут быть образованы из этого подмногоугольника.
Заполнение dp для каждого подмногоугольника:
Для каждого подмногоугольника от i до j, и для каждой возможной вершины k между i и j, обновляем значение dp[i][j], как сумму минимальных значений триангуляций левой и правой частей подмногоугольника, а также значения текущего треугольника, образованного вершинами i, k и j.
3⃣ Возврат результата:
Ответ будет в dp[0][n-1], который хранит минимальный возможный общий балл триангуляции для всего многоугольника.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
У вас есть выпуклый n-сторонний многоугольник, каждая вершина которого имеет целочисленное значение. Вам дан целочисленный массив values, где values[i] - это значение i-й вершины (т.е. по часовой стрелке). Вы должны триангулировать многоугольник на n - 2 треугольника. Для каждого треугольника значение этого треугольника равно произведению значений его вершин, а общий балл триангуляции равен сумме этих значений для всех n - 2 треугольников в триангуляции. Верните наименьший возможный общий балл, который вы можете получить с помощью некоторой триангуляции многоугольника.
Пример:
Input: values = [1,2,3]
Output: 6
Создаем двумерный массив dp, где dp[i][j] будет хранить минимальный возможный общий балл триангуляции многоугольника, состоящего из вершин от i до j.
Проходим по всем возможным длинам подмногоугольников, начиная с треугольников (длина 3) до всего многоугольника (длина n).
Для каждого подмногоугольника находим минимальный возможный общий балл, проверяя все возможные треугольники, которые могут быть образованы из этого подмногоугольника.
Заполнение dp для каждого подмногоугольника:
Для каждого подмногоугольника от i до j, и для каждой возможной вершины k между i и j, обновляем значение dp[i][j], как сумму минимальных значений триангуляций левой и правой частей подмногоугольника, а также значения текущего треугольника, образованного вершинами i, k и j.
Ответ будет в dp[0][n-1], который хранит минимальный возможный общий балл триангуляции для всего многоугольника.
class Solution {
fun minScoreTriangulation(values: IntArray): Int {
val n = values.size
val dp = Array(n) { IntArray(n) }
for (length in 2 until n) {
for (i in 0 until (n - length)) {
val j = i + length
dp[i][j] = Int.MAX_VALUE
for (k in (i + 1) until j) {
dp[i][j] = minOf(dp[i][j], dp[i][k] + dp[k][j] + values[i] * values[j] * values[k])
}
}
}
return dp[0][n - 1]
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 228. Summary Ranges
Сложность: easy
Вам дан отсортированный массив уникальных целых чисел nums.
Диапазон [a,b] - это множество всех целых чисел от a до b (включительно).
Верните наименьший отсортированный список диапазонов, которые покрывают все числа в массиве точно. То есть, каждый элемент nums покрывается ровно одним из диапазонов, и не существует такого целого числа x, чтобы x находился в одном из диапазонов, но не находился в nums.
Каждый диапазон [a,b] в списке должен быть представлен в формате:
"a->b" если a != b
"a" если a == b
Пример:
👨💻 Алгоритм:
1⃣ Создайте список строк ranges, который будет содержать решение задачи, и начните итерацию по всем элементам nums с указателем i = 0. Каждая итерация внешнего цикла представляет собой поиск одного диапазона. Для начала сохраните начало текущего диапазона в start = nums[i].
2⃣ Проверьте, отличается ли следующий элемент в nums на индексе i + 1 от nums[i] на 1 или больше. Если следующий элемент отличается на 1, увеличьте i на 1, чтобы включить (i+1)-й элемент в этот диапазон и продолжайте проверку следующего элемента. Продолжайте добавлять элементы в этот диапазон, пока последовательные элементы отличаются на 1, используя цикл while для выполнения этой логики.
3⃣ Если следующий элемент отличается более чем на 1 или если все элементы в nums уже обработаны, проверьте, равен ли start значению nums[i]. Если start == nums[i], добавьте только start как строку в ranges, так как у нас есть только один элемент в этом диапазоне. Если start != nums[i], добавьте строку start->nums[i] в ranges. Увеличьте i на 1, чтобы начать новый диапазон.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Вам дан отсортированный массив уникальных целых чисел nums.
Диапазон [a,b] - это множество всех целых чисел от a до b (включительно).
Верните наименьший отсортированный список диапазонов, которые покрывают все числа в массиве точно. То есть, каждый элемент nums покрывается ровно одним из диапазонов, и не существует такого целого числа x, чтобы x находился в одном из диапазонов, но не находился в nums.
Каждый диапазон [a,b] в списке должен быть представлен в формате:
"a->b" если a != b
"a" если a == b
Пример:
Input: nums = [0,1,2,4,5,7]
Output: ["0->2","4->5","7"]
Explanation: The ranges are:
[0,2] --> "0->2"
[4,5] --> "4->5"
[7,7] --> "7"
class Solution {
fun summaryRanges(nums: IntArray): List<String> {
val ranges = mutableListOf<String>()
var i = 0
while (i < nums.size) {
val start = nums[i]
while (i + 1 < nums.size && nums[i] + 1 == nums[i + 1]) {
i++
}
if (start != nums[i]) {
ranges.add("$start->${nums[i]}")
} else {
ranges.add("$start")
}
i++
}
return ranges
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Задача: 710. Random Pick with Blacklist
Сложность: hard
Вам дано целое число n и массив уникальных целых чисел blacklist. Разработайте алгоритм выбора случайного целого числа из диапазона [0, n - 1], не входящего в черный список. Любое целое число, находящееся в указанном диапазоне и не входящее в черный список, должно с равной вероятностью быть возвращено. Оптимизируйте алгоритм так, чтобы он минимизировал количество обращений к встроенной функции random вашего языка. Реализуйте класс Solution: Solution(int n, int[] blacklist) Инициализирует объект целым числом n и целым числом из черного списка blacklist. int pick() Возвращает случайное целое число в диапазоне [0, n - 1] и не входящее в черный список.
Пример:
👨💻 Алгоритм:
1⃣ Создайте маппинг для чисел, входящих в черный список, чтобы сопоставить их с числами из диапазона [n - len(blacklist), n - 1], которые не входят в черный список.
2⃣ Создайте массив для хранения возможных чисел для выбора, исключая числа из черного списка.
3⃣ При каждом вызове функции pick() используйте встроенную функцию random для выбора случайного индекса из массива возможных чисел и возвращайте соответствующее значение.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Вам дано целое число n и массив уникальных целых чисел blacklist. Разработайте алгоритм выбора случайного целого числа из диапазона [0, n - 1], не входящего в черный список. Любое целое число, находящееся в указанном диапазоне и не входящее в черный список, должно с равной вероятностью быть возвращено. Оптимизируйте алгоритм так, чтобы он минимизировал количество обращений к встроенной функции random вашего языка. Реализуйте класс Solution: Solution(int n, int[] blacklist) Инициализирует объект целым числом n и целым числом из черного списка blacklist. int pick() Возвращает случайное целое число в диапазоне [0, n - 1] и не входящее в черный список.
Пример:
Input
["Solution", "pick", "pick", "pick", "pick", "pick", "pick", "pick"]
[[7, [2, 3, 5]], [], [], [], [], [], [], []]
Output
[null, 0, 4, 1, 6, 1, 0, 4]
import kotlin.random.Random
class Solution(n: Int, blacklist: IntArray) {
private val map = mutableMapOf<Int, Int>()
private val bound = n - blacklist.size
init {
val blackset = blacklist.toSet()
var whitelist = bound
for (b in blacklist) {
if (b < bound) {
while (blackset.contains(whitelist)) {
whitelist++
}
map[b] = whitelist
whitelist++
}
}
}
fun pick(): Int {
val r = Random.nextInt(bound)
return map.getOrDefault(r, r)
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача №17. Letter Combinations of a Phone Number
Сложность: medium
Учитывая строку, содержащую цифры от 2 до 9 включительно, верните все возможные комбинации букв, которые может представлять число. Верните ответ в любом порядке. Соответствие цифр буквам (как на кнопках телефона) приведено ниже. Обратите внимание, что 1 не соответствует никаким буквам.
Пример:
👨💻 Алгоритм:
1⃣ Проверить, не является ли входная строка пустой, и в этом случае вернуть пустой список.
2⃣ Использовать метод
3⃣ Сопоставить цифры с буквами с помощью метода расширения, позволяющего быстро получать возможные варианты.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Учитывая строку, содержащую цифры от 2 до 9 включительно, верните все возможные комбинации букв, которые может представлять число. Верните ответ в любом порядке. Соответствие цифр буквам (как на кнопках телефона) приведено ниже. Обратите внимание, что 1 не соответствует никаким буквам.
Пример:
Input: digits = "23"
Output: ["ad","ae","af","bd","be","bf","cd","ce","cf"]
fold, чтобы итеративно формировать комбинации, добавляя буквы, соответствующие каждой цифре. class Solution {
fun letterCombinations(digits: String): List<String> =
digits.takeIf { it.isNotEmpty() }?.fold(listOf("")) { acc, c ->
c.letters.flatMap { letter -> acc.map { it + letter } }
} ?: emptyList()
private val Char.letters get() = when(this) {
'2' -> listOf('a', 'b', 'c')
'3' -> listOf('d', 'e', 'f')
'4' -> listOf('g', 'h', 'i')
'5' -> listOf('j', 'k', 'l')
'6' -> listOf('m', 'n', 'o')
'7' -> listOf('p', 'q', 'r', 's')
'8' -> listOf('t', 'u', 'v')
'9' -> listOf('w', 'x', 'y', 'z')
else -> listOf()
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM