Задача: 375. Guess Number Higher or Lower II
Сложность: easy
Мы играем в угадайку. Правила игры следующие:
Я загадываю число между 1 и n.
Вы угадываете число.
Если вы угадаете правильное число, вы выигрываете игру.
Если вы угадаете неправильное число, я скажу вам, загаданное число больше или меньше, и вы продолжите угадывать.
Каждый раз, когда вы угадываете неправильное число x, вы платите x долларов. Если у вас закончились деньги, вы проигрываете игру.
Дано число n. Верните минимальную сумму денег, необходимую для гарантированной победы независимо от того, какое число я загадаю.
Пример:
👨💻 Алгоритм:
1⃣ В методе "грубой силы" для чисел в диапазоне (i, j) выбираем каждое число от i до j в качестве опорного и находим максимальную стоимость из его левых и правых сегментов. Если выбрать число из диапазона (i, (i + j) / 2) как опорное, правый сегмент будет длиннее левого, что приведет к большему максимальному затратам из правого сегмента.
2⃣ Наша цель - уменьшить большие затраты, приходящиеся на правый сегмент. Поэтому целесообразно выбирать опорное число из диапазона ((i + j) / 2, j). В этом случае затраты на оба сегмента будут ближе друг к другу, что минимизирует общую стоимость.
3⃣ Вместо перебора от i до j, итерируем от (i + j) / 2 до j, находя минимально возможные затраты аналогично методу грубой силы.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Мы играем в угадайку. Правила игры следующие:
Я загадываю число между 1 и n.
Вы угадываете число.
Если вы угадаете правильное число, вы выигрываете игру.
Если вы угадаете неправильное число, я скажу вам, загаданное число больше или меньше, и вы продолжите угадывать.
Каждый раз, когда вы угадываете неправильное число x, вы платите x долларов. Если у вас закончились деньги, вы проигрываете игру.
Дано число n. Верните минимальную сумму денег, необходимую для гарантированной победы независимо от того, какое число я загадаю.
Пример:
Input: n = 1
Output: 0
Explanation: There is only one possible number, so you can guess 1 and not have to pay anything.
class Solution {
func calculate(_ low: Int, _ high: Int) -> Int {
if low >= high {
return 0
}
var minres = Int.max
for i in low...high {
let res = i + max(calculate(i + 1, high), calculate(low, i - 1))
minres = min(res, minres)
}
return minres
}
func getMoneyAmount(_ n: Int) -> Int {
return calculate(1, n)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 146. LRU Cache
Сложность: medium
Реализуйте класс LRUCache:
LRUCache(int capacity) - инициализирует LRU-кэш с положительным размером capacity.
int get(int key) - возвращает значение по ключу, если ключ существует, в противном случае возвращает -1.
void put(int key, int value) - обновляет значение по ключу, если ключ существует. В противном случае добавляет пару ключ-значение в кэш. Если количество ключей превышает установленную емкость после этой операции, удаляет наименее недавно использованный ключ.
Функции get и put должны выполняться за среднее время O(1).
Пример:
👨💻 Алгоритм:
1⃣ Метод добавления узла в конец связного списка (add):
Получите текущий узел в конце списка, это "реальный" хвост: tail.prev, обозначим его как previousEnd.
Вставьте node после previousEnd, установив previousEnd.next = node.
Настройте указатели узла: node.prev = previousEnd и node.next = tail.
Обновите tail.prev = node, делая node новым "реальным" хвостом списка.
2⃣ Метод удаления узла из связного списка (remove):
Узел node должен быть удален из списка. Для этого определите узлы nextNode = node.next и prevNode = node.prev.
Чтобы удалить node, переназначьте prevNode.next = nextNode и nextNode.prev = prevNode, эффективно исключая node из списка.
Это превратит, например, последовательность A <-> B <-> C в A <-> C, где prevNode = A и nextNode = C.
3⃣ Методы get и put:
get(int key): Проверьте, существует ли ключ в хэш-карте. Если нет, верните -1. Иначе, получите узел, связанный с ключом, переместите его в конец списка с помощью remove(node) и add(node). Верните node.val.
put(int key, int value): Если ключ уже существует, найдите соответствующий узел и удалите его методом remove. Создайте новый узел с key и value, добавьте его в хэш-карту и в конец списка методом add(node). Если размер кэша превышает установленную емкость после добавления, удалите самый редко используемый узел (который находится в голове списка после фиктивного узла head), затем удалите соответствующий ключ из хэш-карты.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Реализуйте класс LRUCache:
LRUCache(int capacity) - инициализирует LRU-кэш с положительным размером capacity.
int get(int key) - возвращает значение по ключу, если ключ существует, в противном случае возвращает -1.
void put(int key, int value) - обновляет значение по ключу, если ключ существует. В противном случае добавляет пару ключ-значение в кэш. Если количество ключей превышает установленную емкость после этой операции, удаляет наименее недавно использованный ключ.
Функции get и put должны выполняться за среднее время O(1).
Пример:
Input
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
Output
[null, null, null, 1, null, -1, null, -1, 3, 4]
Получите текущий узел в конце списка, это "реальный" хвост: tail.prev, обозначим его как previousEnd.
Вставьте node после previousEnd, установив previousEnd.next = node.
Настройте указатели узла: node.prev = previousEnd и node.next = tail.
Обновите tail.prev = node, делая node новым "реальным" хвостом списка.
Узел node должен быть удален из списка. Для этого определите узлы nextNode = node.next и prevNode = node.prev.
Чтобы удалить node, переназначьте prevNode.next = nextNode и nextNode.prev = prevNode, эффективно исключая node из списка.
Это превратит, например, последовательность A <-> B <-> C в A <-> C, где prevNode = A и nextNode = C.
get(int key): Проверьте, существует ли ключ в хэш-карте. Если нет, верните -1. Иначе, получите узел, связанный с ключом, переместите его в конец списка с помощью remove(node) и add(node). Верните node.val.
put(int key, int value): Если ключ уже существует, найдите соответствующий узел и удалите его методом remove. Создайте новый узел с key и value, добавьте его в хэш-карту и в конец списка методом add(node). Если размер кэша превышает установленную емкость после добавления, удалите самый редко используемый узел (который находится в голове списка после фиктивного узла head), затем удалите соответствующий ключ из хэш-карты.
class Node {
var key: Int
var value: Int
var next: Node?
var prev: Node?
init(_ key: Int, _ value: Int) {
self.key = key
self.value = value
}
}
class LRUCache {
private var capacity: Int
private var dict = [Int: Node]()
private let head: Node
private let tail: Node
init(_ capacity: Int) {
self.capacity = capacity
head = Node(-1, -1)
tail = Node(-1, -1)
head.next = tail
tail.prev = head
}
func get(_ key: Int) -> Int {
guard let node = dict[key] else {
return -1
}
remove(node)
add(node)
return node.value
}
func put(_ key: Int, _ value: Int) {
if let node = dict[key] {
remove(node)
}
let newNode = Node(key, value)
add(newNode)
dict[key] = newNode
if dict.count > capacity {
if let nodeToDelete = head.next {
remove(nodeToDelete)
dict.removeValue(forKey: nodeToDelete.key)
}
}
}
private func add(_ node: Node) {
let prev = tail.prev
prev?.next = node
node.prev = prev
node.next = tail
tail.prev = node
}
private func remove(_ node: Node) {
let prev = node.prev
let next = node.next
prev?.next = next
next?.prev = prev
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 553. Optimal Division
Сложность: medium
Дано целочисленный массив nums. Соседние целые числа в nums будут выполнять деление с плавающей запятой.
Например, для nums = [2,3,4] мы будем вычислять выражение "2/3/4".
Однако, вы можете добавить любое количество скобок в любое место, чтобы изменить приоритет операций. Вы хотите добавить эти скобки так, чтобы значение выражения после вычисления было максимальным.
Верните соответствующее выражение, которое имеет максимальное значение в строковом формате.
Пример:
👨💻 Алгоритм:
1⃣ Разверните оба числа. Инициализируйте массив ans с (N+M) нулями. Для каждой цифры во втором числе: держите переменную переноса, изначально равную 0. Инициализируйте массив (currentResult), начинающийся с некоторых нулей в зависимости от места цифры во втором числе.
2⃣ Для каждой цифры первого числа: умножьте цифру второго числа на цифру первого числа и добавьте предыдущий перенос к результату умножения. Возьмите остаток от деления на 10, чтобы получить последнюю цифру. Добавьте последнюю цифру к массиву currentResult. Разделите результат умножения на 10, чтобы получить новое значение переноса.
3⃣ После итерации по каждой цифре в первом числе, если перенос не равен нулю, добавьте перенос к массиву currentResult. Добавьте currentResult к массиву ans. Если последняя цифра в ans равна нулю, перед разворотом ans удалите этот ноль, чтобы избежать ведущего нуля в окончательном ответе. Разверните ans и верните его.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дано целочисленный массив nums. Соседние целые числа в nums будут выполнять деление с плавающей запятой.
Например, для nums = [2,3,4] мы будем вычислять выражение "2/3/4".
Однако, вы можете добавить любое количество скобок в любое место, чтобы изменить приоритет операций. Вы хотите добавить эти скобки так, чтобы значение выражения после вычисления было максимальным.
Верните соответствующее выражение, которое имеет максимальное значение в строковом формате.
Пример:
Input: nums = [1000,100,10,2]
Output: "1000/(100/10/2)"
Explanation: 1000/(100/10/2) = 1000/((100/10)/2) = 200
However, the bold parenthesis in "1000/((100/10)/2)" are redundant since they do not influence the operation priority.
So you should return "1000/(100/10/2)".
Other cases:
1000/(100/10)/2 = 50
1000/(100/(10/2)) = 50
1000/100/10/2 = 0.5
1000/100/(10/2) = 2
class Solution {
private func addStrings(_ num1: [Int], _ num2: [Int]) -> [Int] {
var ans = [Int]()
var carry = 0
let n1 = num1.count
let n2 = num2.count
for i in 0..<max(n1, n2) + 1 {
let digit1 = i < n1 ? num1[i] : 0
let digit2 = i < n2 ? num2[i] : 0
let sum = digit1 + digit2 + carry
carry = sum / 10
ans.append(sum % 10)
}
return ans
}
private func multiplyOneDigit(_ firstNumber: String, _ secondNumberDigit: Character, _ numZeros: Int) -> [Int] {
var currentResult = [Int](repeating: 0, count: numZeros)
var carry = 0
for digit in firstNumber {
let multiplication = (secondNumberDigit.wholeNumberValue! * digit.wholeNumberValue!) + carry
carry = multiplication / 10
currentResult.append(multiplication % 10)
}
if carry != 0 {
currentResult.append(carry)
}
return currentResult
}
func multiply(_ firstNumber: String, _ secondNumber: String) -> String {
if firstNumber == "0" || secondNumber == "0" {
return "0"
}
let firstNumber = String(firstNumber.reversed())
let secondNumber = String(secondNumber.reversed())
var ans = [Int](repeating: 0, count: firstNumber.count + secondNumber.count)
for (i, digit) in secondNumber.enumerated() {
ans = addStrings(multiplyOneDigit(firstNumber, digit, i), ans)
}
while ans.last == 0 {
ans.removeLast()
}
return ans.reversed().map { String($0) }.joined()
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 680. Valid Palindrome II
Сложность: easy
Дана строка s, вернуть true, если s может быть палиндромом после удаления не более одного символа из нее.
Пример:
👨💻 Алгоритм:
1⃣ Создайте вспомогательную функцию checkPalindrome, которая принимает строку s и два указателя i и j. Эта функция возвращает логическое значение, указывающее, является ли подстрока s.substring(i, j) палиндромом.
2⃣ Инициализируйте два указателя: i = 0 и j = s.length() - 1. Пока i < j, проверьте, совпадают ли символы в индексах i и j. Если нет, это значит, что нам нужно удалить один из этих символов.
3⃣ Попробуйте оба варианта, используя checkPalindrome. Верните true, если либо checkPalindrome(s, i, j - 1), либо checkPalindrome(s, i + 1, j) возвращает true. Если мы выходим из цикла while, это значит, что исходная строка является палиндромом. Поскольку нам не нужно было использовать удаление, следует вернуть true.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дана строка s, вернуть true, если s может быть палиндромом после удаления не более одного символа из нее.
Пример:
Input: s = "aba"
Output: true
class Solution {
private func checkPalindrome(_ s: String, _ i: Int, _ j: Int) -> Bool {
var i = i
var j = j
let sArray = Array(s)
while i < j {
if sArray[i] != sArray[j] {
return false
}
i += 1
j -= 1
}
return true
}
func validPalindrome(_ s: String) -> Bool {
var i = 0
var j = s.count - 1
let sArray = Array(s)
while i < j {
if sArray[i] != sArray[j] {
return checkPalindrome(s, i, j - 1) || checkPalindrome(s, i + 1, j)
}
i += 1
j -= 1
}
return true
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1480. Running Sum of 1d Array
Сложность: easy
Дан массив nums. Мы определяем текущую сумму массива как runningSum[i] = сумма(nums[0]…nums[i]).
Верните массив текущих сумм для nums.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация:
Определите массив result.
Инициализируйте первый элемент массива result первым элементом входного массива nums.
2⃣ Вычисление текущих сумм:
На индексе i добавьте сумму элемента nums[i] и предыдущей текущей суммы result[i - 1] в массив result.
3⃣ Повторение для всех индексов:
Повторите шаг 2 для всех индексов от 1 до n-1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан массив nums. Мы определяем текущую сумму массива как runningSum[i] = сумма(nums[0]…nums[i]).
Верните массив текущих сумм для nums.
Пример:
Input: nums = [1,2,3,4]
Output: [1,3,6,10]
Explanation: Running sum is obtained as follows: [1, 1+2, 1+2+3, 1+2+3+4].
Определите массив result.
Инициализируйте первый элемент массива result первым элементом входного массива nums.
На индексе i добавьте сумму элемента nums[i] и предыдущей текущей суммы result[i - 1] в массив result.
Повторите шаг 2 для всех индексов от 1 до n-1.
class Solution {
func runningSum(_ nums: [Int]) -> [Int] {
var result = [Int](repeating: 0, count: nums.count)
result[0] = nums[0]
for i in 1..<nums.count {
result[i] = result[i - 1] + nums[i]
}
return result
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 958. Check Completeness of a Binary Tree
Сложность: medium
Дан корень бинарного дерева, определите, является ли оно полным бинарным деревом.
В полном бинарном дереве каждый уровень, за исключением, возможно, последнего, полностью заполнен, и все узлы на последнем уровне расположены как можно левее. На последнем уровне h может быть от 1 до 2^h узлов включительно.
Пример:
👨💻 Алгоритм:
1⃣ Если корень дерева равен null, верните true.
2⃣ Инициализируйте переменную nullNodeFound как false для отслеживания того, встречался ли уже null-узел. Создайте очередь и поместите в неё корень дерева.
3⃣ Пока очередь не пуста:
Извлеките первый элемент из очереди.
Если элемент равен null, установите nullNodeFound в true.
Если элемент не равен null, проверьте, встречался ли уже null-узел. Если nullNodeFound равен true, верните false. В противном случае добавьте в очередь левого и правого потомков текущего узла.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан корень бинарного дерева, определите, является ли оно полным бинарным деревом.
В полном бинарном дереве каждый уровень, за исключением, возможно, последнего, полностью заполнен, и все узлы на последнем уровне расположены как можно левее. На последнем уровне h может быть от 1 до 2^h узлов включительно.
Пример:
Input: root = [1,2,3,4,5,6]
Output: true
Explanation: Every level before the last is full (ie. levels with node-values {1} and {2, 3}), and all nodes in the last level ({4, 5, 6}) are as far left as possible.
Извлеките первый элемент из очереди.
Если элемент равен null, установите nullNodeFound в true.
Если элемент не равен null, проверьте, встречался ли уже null-узел. Если nullNodeFound равен true, верните false. В противном случае добавьте в очередь левого и правого потомков текущего узла.
class Solution {
func isCompleteTree(_ root: TreeNode?) -> Bool {
if root == nil {
return true
}
var queue = [TreeNode?]()
queue.append(root)
var nullNodeFound = false
while !queue.isEmpty {
let node = queue.removeFirst()
if node == nil {
nullNodeFound = true
} else {
if nullNodeFound {
return false
}
queue.append(node?.left)
queue.append(node?.right)
}
}
return true
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 941. Valid Mountain Array
Сложность: easy
Задав массив целых чисел arr, верните true тогда и только тогда, когда он является допустимым горным массивом. Напомним, что arr является горным массивом тогда и только тогда, когда: arr.length >= 3 Существует некоторое i с 0 < i < arr.length - 1 такое, что: arr[0] < arr[1] < ... < arr[i - 1] < arr[i] arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
Пример:
👨💻 Алгоритм:
1⃣ Убедиться, что длина массива не меньше 3.
2⃣ Найти вершину горы, которая удовлетворяет условиям горного массива.
Проверить, что все элементы слева от вершины строго возрастают.
Проверить, что все элементы справа от вершины строго убывают.
3⃣ Вернуть true, если оба условия выполнены, иначе вернуть false.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Задав массив целых чисел arr, верните true тогда и только тогда, когда он является допустимым горным массивом. Напомним, что arr является горным массивом тогда и только тогда, когда: arr.length >= 3 Существует некоторое i с 0 < i < arr.length - 1 такое, что: arr[0] < arr[1] < ... < arr[i - 1] < arr[i] arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
Пример:
Input: arr = [2,1]
Output: false
Проверить, что все элементы слева от вершины строго возрастают.
Проверить, что все элементы справа от вершины строго убывают.
class Solution {
func validMountainArray(_ arr: [Int]) -> Bool {
if arr.count < 3 {
return false
}
var i = 1
while i < arr.count && arr[i] > arr[i - 1] {
i += 1
}
if i == 1 || i == arr.count {
return false
}
while i < arr.count && arr[i] < arr[i - 1] {
i += 1
}
return i == arr.count
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 25. Reverse Nodes in k-Group
Сложность: hard
Учитывая заголовок связанного списка, поменяйте местами узлы списка k за раз и верните измененный список.
k — целое положительное число, меньшее или равное длине связанного списка. Если количество узлов не кратно k, то пропущенные узлы в конечном итоге должны остаться такими, какие они есть.
Вы не можете изменять значения в узлах списка, можно изменять только сами узлы.
Пример:
👨💻 Алгоритм:
1⃣ Определяем длину списка, чтобы знать, сколько полных групп из k узлов можно перевернуть.
2⃣ Используем фиктивный узел (dummy) для удобного управления указателями.
3⃣ Переворачиваем группы по k узлов, изменяя связи в списке.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Учитывая заголовок связанного списка, поменяйте местами узлы списка k за раз и верните измененный список.
k — целое положительное число, меньшее или равное длине связанного списка. Если количество узлов не кратно k, то пропущенные узлы в конечном итоге должны остаться такими, какие они есть.
Вы не можете изменять значения в узлах списка, можно изменять только сами узлы.
Пример:
Input: head = [1,2,3,4,5], k = 3
Output: [3,2,1,4,5]
class ListNode {
var val: Int
var next: ListNode?
init(_ val: Int) {
self.val = val
self.next = nil
}
}
func reverseKGroup(_ head: ListNode?, _ k: Int) -> ListNode? {
if head == nil || k == 1 {
return head
}
let dummy = ListNode(0)
dummy.next = head
var current: ListNode? = dummy
var next: ListNode?
var prev: ListNode? = dummy
var count = 0
while current?.next != nil {
current = current?.next
count += 1
}
while count >= k {
current = prev?.next
next = current?.next
for _ in 1..<k {
current?.next = next?.next
next?.next = prev?.next
prev?.next = next
next = current?.next
}
prev = current
count -= k
}
return dummy.next
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 131. Palindrome Partitioning
Сложность: Medium
Дана строка s. Разделите строку таким образом, чтобы каждая подстрока разделения была палиндромом. Верните все возможные варианты разделения строки s на палиндромы.
Пример:
👨💻 Алгоритм:
1⃣ Инициация рекурсивного обхода:
В алгоритме обратного отслеживания (backtracking) мы рекурсивно пробегаем по строке, используя метод поиска в глубину (depth-first search). Для каждого рекурсивного вызова задаётся начальный индекс строки start.
Итеративно генерируем все возможные подстроки, начиная с индекса start. Индекс end увеличивается от start до конца строки.
2⃣ Проверка на палиндром и продолжение поиска:
Для каждой сгенерированной подстроки проверяем, является ли она палиндромом.
Если подстрока оказывается палиндромом, она становится потенциальным кандидатом. Добавляем подстроку в currentList и выполняем поиск в глубину для оставшейся части строки. Если текущая подстрока заканчивается на индексе end, то end+1 становится начальным индексом для следующего рекурсивного вызова.
3⃣ Возврат (Backtracking) и сохранение результатов:
Возвращаемся, если начальный индекс start больше или равен длине строки, и добавляем currentList в результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: Medium
Дана строка s. Разделите строку таким образом, чтобы каждая подстрока разделения была палиндромом. Верните все возможные варианты разделения строки s на палиндромы.
Пример:
Input: s = "aab"
Output: [["a","a","b"],["aa","b"]]
В алгоритме обратного отслеживания (backtracking) мы рекурсивно пробегаем по строке, используя метод поиска в глубину (depth-first search). Для каждого рекурсивного вызова задаётся начальный индекс строки start.
Итеративно генерируем все возможные подстроки, начиная с индекса start. Индекс end увеличивается от start до конца строки.
Для каждой сгенерированной подстроки проверяем, является ли она палиндромом.
Если подстрока оказывается палиндромом, она становится потенциальным кандидатом. Добавляем подстроку в currentList и выполняем поиск в глубину для оставшейся части строки. Если текущая подстрока заканчивается на индексе end, то end+1 становится начальным индексом для следующего рекурсивного вызова.
Возвращаемся, если начальный индекс start больше или равен длине строки, и добавляем currentList в результат.
class Solution {
func partition(_ s: String) -> [[String]] {
var result = [[String]]()
var currentList = [String]()
dfs(&result, s, 0, ¤tList)
return result
}
private func dfs(_ result: inout [[String]], _ s: String, _ start: Int, _ currentList: inout [String]) {
if start >= s.count {
result.append(currentList)
}
for end in start..<s.count {
if isPalindrome(s, start, end) {
let range = s.index(s.startIndex, offsetBy: start)...s.index(s.startIndex, offsetBy: end)
currentList.append(String(s[range]))
dfs(&result, s, end + 1, ¤tList)
currentList.removeLast()
}
}
}
private func isPalindrome(_ s: String, _ low: Int, _ high: Int) -> Bool {
var low = low
var high = high
let sArray = Array(s)
while low < high {
if sArray[low] != sArray[high] {
return false
}
low += 1
high -= 1
}
return true
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 409. Longest Palindrome
Сложность: easy
Если задана строка s, состоящая из строчных или прописных букв, верните длину самого длинного палиндрома, который можно построить из этих букв. Буквы чувствительны к регистру, например, "Aa" не считается палиндромом.
Пример:
👨💻 Алгоритм:
1⃣ Создайте словарь для подсчета количества каждого символа в строке.
2⃣ Пройдитесь по словарю и добавьте четное количество каждого символа к длине палиндрома. Если встречается нечетное количество символа, добавьте (count - 1) к длине палиндрома.
3⃣ Если есть хотя бы один символ с нечетным количеством, добавьте 1 к длине палиндрома для центрального символа.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Если задана строка s, состоящая из строчных или прописных букв, верните длину самого длинного палиндрома, который можно построить из этих букв. Буквы чувствительны к регистру, например, "Aa" не считается палиндромом.
Пример:
Input: s = "abccccdd"
Output: 7
func longestPalindrome(_ s: String) -> Int {
var charCount = [Character: Int]()
for char in s {
charCount[char, default: 0] += 1
}
var length = 0
var oddFound = false
for count in charCount.values {
if count % 2 == 0 {
length += count
} else {
length += count - 1
oddFound = true
}
}
return oddFound ? length + 1 : length
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1146. Snapshot Array
Сложность: medium
Реализуйте SnapshotArray, который поддерживает следующий интерфейс:
SnapshotArray(int length) инициализирует структуру данных, похожую на массив, с заданной длиной. Изначально каждый элемент равен 0.
void set(index, val) устанавливает элемент с заданным индексом равным val.
int snap() делает снимок массива и возвращает snap_id: общее количество вызовов snap() минус 1.
int get(index, snap_id) возвращает значение на заданном индексе в момент, когда мы сделали снимок с указанным snap_id.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация: Для каждого элемента nums[i] в массиве создайте пустой список для хранения его исторических значений в формате [snap_id, value]. Инициализируйте каждый список, добавив первую запись [0, 0].
2⃣ Метод set: Добавьте историческую запись [snap_id, value] в список записей historyRecords[index].
3⃣ Методы snap и get:
Метод snap возвращает snap_id и увеличивает его на 1.
Метод get использует бинарный поиск, чтобы найти индекс последней вставки snap_id в данный снимок (целевой индекс будет snap_index - 1). Возвращает historyRecords[index][snap_index - 1][1].
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Реализуйте SnapshotArray, который поддерживает следующий интерфейс:
SnapshotArray(int length) инициализирует структуру данных, похожую на массив, с заданной длиной. Изначально каждый элемент равен 0.
void set(index, val) устанавливает элемент с заданным индексом равным val.
int snap() делает снимок массива и возвращает snap_id: общее количество вызовов snap() минус 1.
int get(index, snap_id) возвращает значение на заданном индексе в момент, когда мы сделали снимок с указанным snap_id.
Пример:
Input: ["SnapshotArray","set","snap","set","get"]
[[3],[0,5],[],[0,6],[0,0]]
Output: [null,null,0,null,5]
Explanation:
SnapshotArray snapshotArr = new SnapshotArray(3); // set the length to be 3
snapshotArr.set(0,5); // Set array[0] = 5
snapshotArr.snap(); // Take a snapshot, return snap_id = 0
snapshotArr.set(0,6);
snapshotArr.get(0,0); // Get the value of array[0] with snap_id = 0, return 5
Метод snap возвращает snap_id и увеличивает его на 1.
Метод get использует бинарный поиск, чтобы найти индекс последней вставки snap_id в данный снимок (целевой индекс будет snap_index - 1). Возвращает historyRecords[index][snap_index - 1][1].
class SnapshotArray {
var snapId = 0
var historyRecords: [Int: [Int: Int]]
init(_ length: Int) {
historyRecords = [Int: [Int: Int]]()
for i in 0..<length {
historyRecords[i] = [0: 0]
}
}
func set(_ index: Int, _ val: Int) {
historyRecords[index]![snapId] = val
}
func snap() -> Int {
defer { snapId += 1 }
return snapId
}
func get(_ index: Int, _ snapId: Int) -> Int {
let record = historyRecords[index]!
let keys = Array(record.keys).sorted()
for key in keys.reversed() {
if key <= snapId {
return record[key]!
}
}
return 0
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1518. Water Bottles
Сложность: easy
Есть numBottles бутылок с водой, которые изначально наполнены водой. Вы можете обменять numExchange пустых бутылок на одну полную бутылку воды на рынке.
Операция питья полной бутылки воды превращает её в пустую бутылку.
Даны два целых числа numBottles и numExchange. Верните максимальное количество бутылок с водой, которые вы можете выпить.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте переменную ответа consumedBottles значением 0.
2⃣ Продолжайте выполнять следующие действия, пока количество numBottles больше или равно numExchange:
— Выпейте numExchange количество полных бутылок, т.е. добавьте numExchange к consumedBottles.
— Уменьшите numExchange от доступных полных бутылок numBottles.
— Обменяйте пустые бутылки на одну полную бутылку, т.е. увеличьте numBottles на одну.
3⃣ Верните consumedBottles + numBottles.
😎 Решение
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Есть numBottles бутылок с водой, которые изначально наполнены водой. Вы можете обменять numExchange пустых бутылок на одну полную бутылку воды на рынке.
Операция питья полной бутылки воды превращает её в пустую бутылку.
Даны два целых числа numBottles и numExchange. Верните максимальное количество бутылок с водой, которые вы можете выпить.
Пример:
Input: numBottles = 9, numExchange = 3
Output: 13
Explanation: You can exchange 3 empty bottles to get 1 full water bottle.
Number of water bottles you can drink: 9 + 3 + 1 = 13.
— Выпейте numExchange количество полных бутылок, т.е. добавьте numExchange к consumedBottles.
— Уменьшите numExchange от доступных полных бутылок numBottles.
— Обменяйте пустые бутылки на одну полную бутылку, т.е. увеличьте numBottles на одну.
class Solution {
func numWaterBottles(_ numBottles: Int, _ numExchange: Int) -> Int {
var numBottles = numBottles
var consumedBottles = 0
while numBottles >= numExchange {
consumedBottles += numExchange
numBottles -= numExchange
numBottles += 1
}
return consumedBottles + numBottles
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 686. Repeated String Match
Сложность: medium
Даны две строки a и b. Верните минимальное количество повторений строки a, чтобы строка b стала её подстрокой. Если сделать b подстрокой a невозможно, верните -1.
Обратите внимание: строка "abc", повторенная 0 раз, это "", повторенная 1 раз - "abc", повторенная 2 раза - "abcabc".
Пример:
👨💻 Алгоритм:
1⃣ Найти минимальное количество повторений строки A, чтобы её длина стала больше или равна длине B. Это значение q = ceil(len(B) / len(A)).
2⃣ Проверить, является ли B подстрокой строки A, повторенной q раз. Если да, вернуть q. Иначе, проверить строку A, повторенную (q+1) раз. Если B является подстрокой этой строки, вернуть q+1.
3⃣ Если B не является подстрокой ни в одном из случаев, вернуть -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Даны две строки a и b. Верните минимальное количество повторений строки a, чтобы строка b стала её подстрокой. Если сделать b подстрокой a невозможно, верните -1.
Обратите внимание: строка "abc", повторенная 0 раз, это "", повторенная 1 раз - "abc", повторенная 2 раза - "abcabc".
Пример:
Input: a = "abcd", b = "cdabcdab"
Output: 3
Explanation: We return 3 because by repeating a three times "abcdabcdabcd", b is a substring of it.
class Solution {
func repeatedStringMatch(_ A: String, _ B: String) -> Int {
var q = 1
var S = A
while S.count < B.count {
S += A
q += 1
}
if S.contains(B) {
return q
}
if (S + A).contains(B) {
return q + 1
}
return -1
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 170. Two Sum III - Data structure design
Сложность: easy
Разработайте структуру данных, которая принимает поток целых чисел и проверяет, есть ли в ней пара чисел, сумма которых равна определенному значению.
Реализуйте класс TwoSum:
- TwoSum() инициализирует объект TwoSum с изначально пустым массивом.
- void add(int number) добавляет число в структуру данных.
- boolean find(int value) возвращает true, если существует хотя бы одна пара чисел, сумма которых равна значению value, в противном случае возвращает false.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация указателей:
Инициализируйте два указателя low и high, которые указывают на первый и последний элементы списка соответственно.
2⃣ Итерация с использованием двух указателей:
Запустите цикл для итерации по списку. Цикл завершится, когда будет найдено решение с двумя суммами или когда два указателя встретятся.
На каждом шаге цикла перемещайте один из указателей в зависимости от различных условий:
Если сумма элементов, на которые указывают текущие указатели, меньше желаемого значения, то необходимо попытаться увеличить сумму для достижения желаемого значения, то есть переместить указатель low вперёд для получения большего значения.
Если сумма элементов больше желаемого значения, то следует попытаться уменьшить сумму, перемещая указатель high в сторону указателя low.
Если сумма равна желаемому значению, можно сразу выполнить возврат из функции.
3⃣ Завершение цикла:
Если цикл завершается тем, что два указателя встречаются, то можно быть уверенным, что решения для желаемого значения не существует.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Разработайте структуру данных, которая принимает поток целых чисел и проверяет, есть ли в ней пара чисел, сумма которых равна определенному значению.
Реализуйте класс TwoSum:
- TwoSum() инициализирует объект TwoSum с изначально пустым массивом.
- void add(int number) добавляет число в структуру данных.
- boolean find(int value) возвращает true, если существует хотя бы одна пара чисел, сумма которых равна значению value, в противном случае возвращает false.
Пример:
Input
["TwoSum", "add", "add", "add", "find", "find"]
[[], [1], [3], [5], [4], [7]]
Output
[null, null, null, null, true, false]
Инициализируйте два указателя low и high, которые указывают на первый и последний элементы списка соответственно.
Запустите цикл для итерации по списку. Цикл завершится, когда будет найдено решение с двумя суммами или когда два указателя встретятся.
На каждом шаге цикла перемещайте один из указателей в зависимости от различных условий:
Если сумма элементов, на которые указывают текущие указатели, меньше желаемого значения, то необходимо попытаться увеличить сумму для достижения желаемого значения, то есть переместить указатель low вперёд для получения большего значения.
Если сумма элементов больше желаемого значения, то следует попытаться уменьшить сумму, перемещая указатель high в сторону указателя low.
Если сумма равна желаемому значению, можно сразу выполнить возврат из функции.
Если цикл завершается тем, что два указателя встречаются, то можно быть уверенным, что решения для желаемого значения не существует.
class TwoSum {
private var nums = [Int: Int]()
init() {}
func add(_ number: Int) {
nums[number, default: 0] += 1
}
func find(_ value: Int) -> Bool {
for (num, count) in nums {
let complement = value - num
if (complement != num && nums[complement] != nil) ||
(complement == num && count > 1) {
return true
}
}
return false
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1133. Largest Unique Number
Сложность: easy
Вам Дан целочисленный массив nums, верните наибольшее целое число, которое встречается только один раз. Если ни одно целое число не встречается один раз, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Создайте хеш-таблицу для хранения количества каждого числа в массиве.
2⃣ Пройдите по массиву и заполните хеш-таблицу количеством каждого числа.
3⃣ Инициализируйте результат значением -1. Пройдите по хеш-таблице и если значение ключа равно 1, установите результат равным максимальному значению между ключом и текущим результатом. Верните результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Вам Дан целочисленный массив nums, верните наибольшее целое число, которое встречается только один раз. Если ни одно целое число не встречается один раз, верните -1.
Пример:
Input: nums = [5,7,3,9,4,9,8,3,1]
Output: 8
Explanation: The maximum integer in the array is 9 but it is repeated. The number 8 occurs only once, so it is the answer.
class Solution {
func largestUniqueNumber(_ nums: [Int]) -> Int {
var count = [Int: Int]()
for num in nums {
count[num, default: 0] += 1
}
var result = -1
for (key, value) in count {
if value == 1 {
result = max(result, key)
}
}
return result
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 435. Non-overlapping Intervals
Сложность: medium
Дан массив интервалов intervals, где intervals[i] = [starti, endi]. Верните минимальное количество интервалов, которые нужно удалить, чтобы остальные интервалы не пересекались.
Пример:
👨💻 Алгоритм:
1⃣ Отсортируйте интервалы по времени окончания.
2⃣ Инициализируйте переменную ответа ans = 0 и целое число k для представления самого последнего времени окончания. k следует инициализировать небольшим значением, например, INT_MIN.
3⃣ Итеративно пройдитесь по интервалам. Для каждого интервала: Если время начала больше или равно k, обновите k до времени окончания текущего интервала. В противном случае увеличьте ans. Верните ans.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив интервалов intervals, где intervals[i] = [starti, endi]. Верните минимальное количество интервалов, которые нужно удалить, чтобы остальные интервалы не пересекались.
Пример:
Input: intervals = [[1,2],[2,3],[3,4],[1,3]]
Output: 1
Explanation: [1,3] can be removed and the rest of the intervals are non-overlapping.
class Solution {
func eraseOverlapIntervals(_ intervals: [[Int]]) -> Int {
let sortedIntervals = intervals.sorted { $0[1] < $1[1] }
var ans = 0
var k = Int.min
for interval in sortedIntervals {
let x = interval[0]
let y = interval[1]
if x >= k {
k = y
} else {
ans += 1
}
}
return ans
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 787. Cheapest Flights Within K Stops
Сложность: medium
Есть n городов, соединенных некоторым количеством рейсов. Вам дан массив flights, где flights[i] = [fromi, toi, pricei] указывает на то, что существует рейс из города fromi в город toi с ценой pricei.
Также даны три целых числа src, dst и k. Верните самую дешевую цену от src до dst с не более чем k остановками. Если такого маршрута нет, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Создайте список смежности, где adj[X] содержит всех соседей узла X и соответствующую цену, которую нужно заплатить, чтобы перейти к соседу. Инициализируйте массив dist, хранящий минимальную цену для достижения узла из узла src. Инициализируйте его большими значениями. Инициализируйте очередь, хранящую пары {node, distance}. Изначально очередь должна содержать только {src, 0}. Создайте переменную stops и установите ее значение равным 0.
2⃣ Выполняйте поиск в ширину (BFS), пока очередь не станет пустой или пока stops > k. Итерируйте по всем узлам на определенном уровне. Это будет сделано путем запуска вложенного цикла и посещения всех узлов, которые в данный момент находятся в очереди. В каждой паре {node, distance} итерируйте по всем соседям узла. Для каждого соседа проверьте, меньше ли dist[neighbor] чем distance + цена ребра. Если это так, обновите dist[neighbor] и добавьте {neighbor, dist[neighbor]} в очередь.
3⃣ После итерации по всем узлам на текущем уровне увеличьте stops на один. Мы посетили все узлы на определенном уровне и готовы посетить следующий уровень узлов. Когда мы достигнем условия, при котором либо очередь станет пустой, либо stops == k, у нас будет наш ответ в dist[dst]. Если dist[dst] не изменилось с начального большого значения, значит, мы никогда не достигли его, и следует вернуть -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Есть n городов, соединенных некоторым количеством рейсов. Вам дан массив flights, где flights[i] = [fromi, toi, pricei] указывает на то, что существует рейс из города fromi в город toi с ценой pricei.
Также даны три целых числа src, dst и k. Верните самую дешевую цену от src до dst с не более чем k остановками. Если такого маршрута нет, верните -1.
Пример:
Input: n = 4, flights = [[0,1,100],[1,2,100],[2,0,100],[1,3,600],[2,3,200]], src = 0, dst = 3, k = 1
Output: 700
Explanation:
The graph is shown above.
The optimal path with at most 1 stop from city 0 to 3 is marked in red and has cost 100 + 600 = 700.
Note that the path through cities [0,1,2,3] is cheaper but is invalid because it uses 2 stops.
class Solution {
func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ k: Int) -> Int {
var adj = [[(Int, Int)]](repeating: [], count: n)
for flight in flights {
adj[flight[0]].append((flight[1], flight[2]))
}
var dist = [Int](repeating: Int.max, count: n)
var q = [(Int, Int)]()
q.append((src, 0))
var stops = 0
while stops <= k && !q.isEmpty {
let sz = q.count
for _ in 0..<sz {
let (node, distance) = q.removeFirst()
for (neighbor, price) in adj[node] {
if price + distance >= dist[neighbor] { continue }
dist[neighbor] = price + distance
q.append((neighbor, dist[neighbor]))
}
}
stops += 1
}
return dist[dst] == Int.max ? -1 : dist[dst]
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1510. Stone Game IV
Сложность: hard
Алиса и Боб поочередно играют в игру, причем Алиса начинает первой.
Изначально в куче n камней. В ходе каждого хода игрок удаляет любое ненулевое количество камней, являющееся квадратом целого числа.
Кроме того, если игрок не может сделать ход, он/она проигрывает игру.
Дано положительное целое число n, верните true, если и только если Алиса выиграет игру, иначе верните false, предполагая, что оба игрока играют оптимально.
Пример:
👨💻 Алгоритм:
1⃣ Функция dfs(remain) представляет собой проверку, должен ли текущий игрок выиграть при оставшихся remain камнях.
2⃣ Для определения результата dfs(n) необходимо итерировать k от 0, чтобы проверить, существует ли такое k, что dfs(remain - k*k) == False. Чтобы предотвратить избыточные вычисления, используйте карту для хранения результатов функции dfs.
3⃣ Не забудьте базовые случаи: dfs(0) == False и dfs(1) == True.
😎 Решение
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Алиса и Боб поочередно играют в игру, причем Алиса начинает первой.
Изначально в куче n камней. В ходе каждого хода игрок удаляет любое ненулевое количество камней, являющееся квадратом целого числа.
Кроме того, если игрок не может сделать ход, он/она проигрывает игру.
Дано положительное целое число n, верните true, если и только если Алиса выиграет игру, иначе верните false, предполагая, что оба игрока играют оптимально.
Пример:
Input: n = 1
Output: true
Explanation: Alice can remove 1 stone winning the game because Bob doesn't have any moves.
class Solution {
func winnerSquareGame(_ n: Int) -> Bool {
var cache = [Int: Bool]()
cache[0] = false
return dfs(&cache, n)
}
func dfs(_ cache: inout [Int: Bool], _ remain: Int) -> Bool {
if let result = cache[remain] {
return result
}
let sqrtRoot = Int(Double(remain).squareRoot())
for i in 1...sqrtRoot {
if !dfs(&cache, remain - i * i) {
cache[remain] = true
return true
}
}
cache[remain] = false
return false
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1003. Check If Word Is Valid After Substitutions
Сложность: medium
Дана строка s, определите, является ли она допустимой. Строка s допустима, если, начиная с пустой строки t = "", вы можете преобразовать t в s, выполнив следующую операцию любое количество раз: вставить строку "abc" в любую позицию в t. Более формально, t становится tleft + "abc" + tright, где t == tleft + tright. Обратите внимание, что tleft и tright могут быть пустыми. Верните true, если s - допустимая строка, иначе верните false.
Пример:
👨💻 Алгоритм:
1⃣ Проверка допустимости длины строки:
Проверьте, что длина строки s кратна 3. Если нет, верните false.
2⃣ Использование стека для проверки:
Инициализируйте пустой стек. Проходите по каждому символу строки s.
Если текущий символ является 'c', проверьте, что два предыдущих символа в стеке - это 'b' и 'a' соответственно. Если это так, удалите 'b' и 'a' из стека. Если нет, верните false.
Если текущий символ не 'c', добавьте его в стек.
3⃣ Проверка остатка стека:
В конце, если стек пуст, верните true. Иначе верните false.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дана строка s, определите, является ли она допустимой. Строка s допустима, если, начиная с пустой строки t = "", вы можете преобразовать t в s, выполнив следующую операцию любое количество раз: вставить строку "abc" в любую позицию в t. Более формально, t становится tleft + "abc" + tright, где t == tleft + tright. Обратите внимание, что tleft и tright могут быть пустыми. Верните true, если s - допустимая строка, иначе верните false.
Пример:
Input: s = "aabcbc"
Output: true
Проверьте, что длина строки s кратна 3. Если нет, верните false.
Инициализируйте пустой стек. Проходите по каждому символу строки s.
Если текущий символ является 'c', проверьте, что два предыдущих символа в стеке - это 'b' и 'a' соответственно. Если это так, удалите 'b' и 'a' из стека. Если нет, верните false.
Если текущий символ не 'c', добавьте его в стек.
В конце, если стек пуст, верните true. Иначе верните false.
class Solution {
func isValid(_ s: String) -> Bool {
if s.count % 3 != 0 {
return false
}
var stack = [Character]()
for char in s {
if char == "c" {
if stack.count < 2 || stack.last! != "b" {
return false
}
stack.removeLast()
if stack.last! != "a" {
return false
}
stack.removeLast()
} else {
stack.append(char)
}
}
return stack.isEmpty
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 150. Evaluate Reverse Polish Notation
Сложность: Medium
Вам дан массив строк под названием tokens, который представляет арифметическое выражение в обратной польской нотации.
Вычислите это выражение. Верните целое число, которое представляет значение этого выражения.
Обратите внимание на следующие моменты:
Допустимые операторы: '+', '-', '*' и '/'.
Каждый операнд может быть целым числом или другим выражением.
Деление двух целых чисел всегда округляется к нулю.
Деление на ноль в выражении отсутствует.
Входные данные представляют собой действительное арифметическое выражение в обратной польской нотации.
Ответ и все промежуточные вычисления можно представить 32-битным целым числом.
Пример:
👨💻 Алгоритм:
1⃣ Обработка входных массивов:
Для языков, таких как Java, где входные данные представлены фиксированным массивом, необходимо определить собственные методы для манипулирования массивом (например, удаление элементов). Это может включать сдвиг элементов для заполнения пробелов после удаления элемента. В качестве альтернативы, копирование массива в ArrayList могло бы упростить удаление, но за счет увеличения сложности по памяти с O(1) до O(n).
2⃣ Обработка типов и деление в Python:
Необходимо быть внимательным при обработке типов в Python во время обработки списка, поскольку числа могут быть представлены как строки или целые числа. Кроме того, стандартное деление в Python не округляет к нулю. Вместо этого использование int(a / b) достигает желаемого результата округления, что отличается от деления нацело int(a // b), которое является другим распространенным подходом.
3⃣ Использование лямбда-функций:
Лямбда-функции могут упростить реализацию арифметических операций (таких как +, -, *, /). Если вы знакомы с лямбда-функциями, они предлагают элегантное решение для динамической обработки операций. Если лямбда-функции новы или не поддерживаются в используемом языке программирования, можно использовать другие методы, а изучение лямбда-функций можно отложить на потом.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: Medium
Вам дан массив строк под названием tokens, который представляет арифметическое выражение в обратной польской нотации.
Вычислите это выражение. Верните целое число, которое представляет значение этого выражения.
Обратите внимание на следующие моменты:
Допустимые операторы: '+', '-', '*' и '/'.
Каждый операнд может быть целым числом или другим выражением.
Деление двух целых чисел всегда округляется к нулю.
Деление на ноль в выражении отсутствует.
Входные данные представляют собой действительное арифметическое выражение в обратной польской нотации.
Ответ и все промежуточные вычисления можно представить 32-битным целым числом.
Пример:
Input: tokens = ["2","1","+","3","*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9
Для языков, таких как Java, где входные данные представлены фиксированным массивом, необходимо определить собственные методы для манипулирования массивом (например, удаление элементов). Это может включать сдвиг элементов для заполнения пробелов после удаления элемента. В качестве альтернативы, копирование массива в ArrayList могло бы упростить удаление, но за счет увеличения сложности по памяти с O(1) до O(n).
Необходимо быть внимательным при обработке типов в Python во время обработки списка, поскольку числа могут быть представлены как строки или целые числа. Кроме того, стандартное деление в Python не округляет к нулю. Вместо этого использование int(a / b) достигает желаемого результата округления, что отличается от деления нацело int(a // b), которое является другим распространенным подходом.
Лямбда-функции могут упростить реализацию арифметических операций (таких как +, -, *, /). Если вы знакомы с лямбда-функциями, они предлагают элегантное решение для динамической обработки операций. Если лямбда-функции новы или не поддерживаются в используемом языке программирования, можно использовать другие методы, а изучение лямбда-функций можно отложить на потом.
class Solution {
private let operations: [String: (Int, Int) -> Int] = [
"+": { $0 + $1 },
"-": { $0 - $1 },
"*": { $0 * $1 },
"/": { $0 / $1 }
]
func evalRPN(_ tokens: [String]) -> Int {
var tokens = tokens
var currentPosition = 0
while tokens.count > 1 {
while operations[tokens[currentPosition]] == nil {
currentPosition += 1
}
let operation = tokens[currentPosition]
let number1 = Int(tokens[currentPosition - 2])!
let number2 = Int(tokens[currentPosition - 1])!
let value = operations[operation]!(number1, number2)
tokens[currentPosition] = String(value)
tokens.removeSubrange((currentPosition - 2)..<currentPosition)
currentPosition -= 1
}
return Int(tokens[0])!
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM