#medium
Задача: 738. Monotone Increasing Digits
Целое число имеет монотонно возрастающие цифры тогда и только тогда, когда каждая пара соседних цифр x и y удовлетворяет x <= y. Задав целое число n, верните наибольшее число, которое меньше или равно n с монотонно возрастающими цифрами.
Пример:
👨💻 Алгоритм:
1⃣ Преобразуйте число в строку для удобства обработки.
2⃣ Найдите позицию, где последовательность перестает быть монотонной.
3⃣ Уменьшите соответствующую цифру и установите все последующие цифры в 9.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 738. Monotone Increasing Digits
Целое число имеет монотонно возрастающие цифры тогда и только тогда, когда каждая пара соседних цифр x и y удовлетворяет x <= y. Задав целое число n, верните наибольшее число, которое меньше или равно n с монотонно возрастающими цифрами.
Пример:
Input: n = 10
Output: 9
func monotoneIncreasingDigits(_ n: Int) -> Int {
var digits = Array(String(n))
var mark = digits.count
for i in stride(from: digits.count - 1, to: 0, by: -1) {
if digits[i] < digits[i - 1] {
mark = i
digits[i - 1] = Character(String(digits[i - 1].wholeNumberValue! - 1))
}
}
for i in mark..<digits.count {
digits[i] = "9"
}
return Int(String(digits))!
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 739. Daily Temperatures
Задав массив целых чисел temperature, представляющих дневные температуры, верните массив answer, такой, что answer[i] - это количество дней, которые нужно подождать после i-го дня, чтобы температура стала теплее. Если в будущем не существует дня, для которого это возможно, сохраните answer[i] == 0.
Пример:
👨💻 Алгоритм:
1⃣ Создайте стек для хранения индексов дней с температурами, для которых еще не найден более теплый день.
2⃣ Пройдите по массиву температур и для каждого дня: Пока текущая температура больше температуры дня на вершине стека, обновляйте массив ответов и удаляйте вершину стека. Добавьте текущий день в стек.
3⃣ Возвращайте массив ответов.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 739. Daily Temperatures
Задав массив целых чисел temperature, представляющих дневные температуры, верните массив answer, такой, что answer[i] - это количество дней, которые нужно подождать после i-го дня, чтобы температура стала теплее. Если в будущем не существует дня, для которого это возможно, сохраните answer[i] == 0.
Пример:
Input: temperatures = [73,74,75,71,69,72,76,73]
Output: [1,1,4,2,1,1,0,0]
func dailyTemperatures(_ T: [Int]) -> [Int] {
var answer = [Int](repeating: 0, count: T.count)
var stack = [Int]()
for i in 0..<T.count {
while let last = stack.last, T[i] > T[last] {
let j = stack.removeLast()
answer[j] = i - j
}
stack.append(i)
}
return answer
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 740. Delete and Earn
Вам дан целочисленный массив nums. Вы хотите максимизировать количество очков, выполнив следующую операцию любое количество раз: Выберите любой элемент nums[i] и удалите его, чтобы заработать nums[i] очков. После этого вы должны удалить каждый элемент, равный nums[i] - 1, и каждый элемент, равный nums[i] + 1. Верните максимальное количество очков, которое вы можете заработать, применив вышеуказанную операцию некоторое количество раз.
Пример:
👨💻 Алгоритм:
1⃣ Подсчитайте количество каждого числа в массиве nums.
2⃣ Используйте динамическое программирование для расчета максимальных очков, которые можно заработать, используя накопленный результат для чисел, меньших текущего. Добавьте текущий день в стек.
3⃣ Для каждого числа num в nums, учитывайте два случая: не брать число или взять число и добавить его очки.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 740. Delete and Earn
Вам дан целочисленный массив nums. Вы хотите максимизировать количество очков, выполнив следующую операцию любое количество раз: Выберите любой элемент nums[i] и удалите его, чтобы заработать nums[i] очков. После этого вы должны удалить каждый элемент, равный nums[i] - 1, и каждый элемент, равный nums[i] + 1. Верните максимальное количество очков, которое вы можете заработать, применив вышеуказанную операцию некоторое количество раз.
Пример:
Input: nums = [3,4,2]
Output: 6
func deleteAndEarn(_ nums: [Int]) -> Int {
var count = [Int: Int]()
for num in nums {
count[num, default: 0] += 1
}
var avoid = 0, using = 0, prev = -1
for num in count.keys.sorted() {
if num - 1 != prev {
let newAvoid = max(avoid, using)
using = num * count[num]! + max(avoid, using)
avoid = newAvoid
} else {
let newAvoid = max(avoid, using)
using = num * count[num]! + avoid
avoid = newAvoid
}
prev = num
}
return max(avoid, using)
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 742. Closest Leaf in a Binary Tree
Если задан корень бинарного дерева, в котором каждый узел имеет уникальное значение, а также задано целое число k, верните значение ближайшего к цели k узла листа дерева. Ближайший к листу узел означает наименьшее количество ребер, пройденных бинарным деревом, чтобы достичь любого листа дерева. Кроме того, узел называется листом, если у него нет дочерних узлов.
Пример:
👨💻 Алгоритм:
1⃣ Пройдите дерево, чтобы найти путь от корня до узла k и сохранить его в список.
2⃣ Найдите все листья и минимальное расстояние до них, используя BFS, начиная с найденного узла k.
3⃣ Верните значение ближайшего листа.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 742. Closest Leaf in a Binary Tree
Если задан корень бинарного дерева, в котором каждый узел имеет уникальное значение, а также задано целое число k, верните значение ближайшего к цели k узла листа дерева. Ближайший к листу узел означает наименьшее количество ребер, пройденных бинарным деревом, чтобы достичь любого листа дерева. Кроме того, узел называется листом, если у него нет дочерних узлов.
Пример:
Input: root = [1,3,2], k = 1
Output: 2
class TreeNode {
var val: Int
var left: TreeNode?
var right: TreeNode?
init(_ val: Int) {
self.val = val
self.left = nil
self.right = nil
}
}
func findClosestLeaf(_ root: TreeNode?, _ k: Int) -> Int {
var path = [TreeNode]()
var leaves = [TreeNode: Int]()
func findPath(_ node: TreeNode?, _ k: Int) -> Bool {
guard let node = node else { return false }
path.append(node)
if node.val == k { return true }
if findPath(node.left, k) || findPath(node.right, k) { return true }
path.removeLast()
return false
}
func findLeaves(_ node: TreeNode?) {
guard let node = node else { return }
if node.left == nil && node.right == nil {
leaves[node] = 0
}
findLeaves(node.left)
findLeaves(node.right)
}
findPath(root, k)
findLeaves(root)
var queue = [(path.last!, 0)]
var visited = Set<TreeNode>()
while !queue.isEmpty {
let (node, dist) = queue.removeFirst()
if leaves[node] != nil {
return node.val
}
visited.insert(node)
if let left = node.left, !visited.contains(left) {
queue.append((left, dist + 1))
}
if let right = node.right, !visited.contains(right) {
queue.append((right, dist + 1))
}
if path.count > 1 {
queue.append((path.removeLast(), dist + 1))
}
}
return -1
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 743. Network Delay Time
Дана сеть из узлов, помеченных от 1 до n. Также дано times - список времен прохождения сигнала в виде направленных ребер times[i] = (ui, vi, wi), где ui - исходный узел, vi - целевой узел, а wi - время прохождения сигнала от источника до цели. Мы пошлем сигнал из заданного узла k. Верните минимальное время, которое потребуется всем узлам, чтобы получить сигнал. Если все узлы не могут получить сигнал, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Представьте граф в виде списка смежности.
2⃣ Используйте алгоритм Дейкстры для нахождения кратчайших путей от узла k до всех других узлов.
3⃣ Найдите максимальное значение среди кратчайших путей к узлам. Если какой-либо узел недостижим, верните -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 743. Network Delay Time
Дана сеть из узлов, помеченных от 1 до n. Также дано times - список времен прохождения сигнала в виде направленных ребер times[i] = (ui, vi, wi), где ui - исходный узел, vi - целевой узел, а wi - время прохождения сигнала от источника до цели. Мы пошлем сигнал из заданного узла k. Верните минимальное время, которое потребуется всем узлам, чтобы получить сигнал. Если все узлы не могут получить сигнал, верните -1.
Пример:
Input: times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2
Output: 2
import Foundation
func networkDelayTime(_ times: [[Int]], _ n: Int, _ k: Int) -> Int {
var graph = [Int: [(Int, Int)]]()
for i in 1...n {
graph[i] = []
}
for time in times {
graph[time[0]]?.append((time[1], time[2]))
}
var minHeap = [(0, k)]
var minTime = [Int: Int]()
for i in 1...n {
minTime[i] = Int.max
}
minTime[k] = 0
while !minHeap.isEmpty {
minHeap.sort { $0.0 < $1.0 }
let (time, node) = minHeap.removeFirst()
if let neighbors = graph[node] {
for (neighbor, t) in neighbors {
let newTime = time + t
if newTime < minTime[neighbor]! {
minTime[neighbor] = newTime
minHeap.append((newTime, neighbor))
}
}
}
}
let maxTime = minTime.values.max()!
return maxTime == Int.max ? -1 : maxTime
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 1522. Diameter of N-Ary Tree
Дано корневое дерево N-арности, нужно вычислить длину диаметра дерева.
Диаметр N-арного дерева - это длина самого длинного пути между любыми двумя узлами в дереве. Этот путь может проходить или не проходить через корень.
(Входная сериализация N-арного дерева представлена их обходом в порядке уровней, каждая группа дочерних узлов разделена значением null.)
Пример:
👨💻 Алгоритм:
1⃣ Определите функцию height(node), которая возвращает высоту узла. Функция может быть реализована рекурсивно, основываясь на вычислении максимальной высоты среди всех дочерних узлов плюс один.
2⃣ Внутри функции height(node) выберите две наибольшие высоты среди дочерних узлов. Эти два значения помогут вычислить длину пути, которая будет кандидатом на диаметр всего дерева.
3⃣ Существует два подхода для выбора двух наибольших высот: Первый способ заключается в хранении высот всех дочерних узлов в массиве, последующей сортировке массива и выборе двух наибольших элементов. Второй способ использует две переменные, которые отслеживают текущие два наибольших значения. Во время итерации по всем высотам эти переменные обновляются соответствующим образом.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 1522. Diameter of N-Ary Tree
Дано корневое дерево N-арности, нужно вычислить длину диаметра дерева.
Диаметр N-арного дерева - это длина самого длинного пути между любыми двумя узлами в дереве. Этот путь может проходить или не проходить через корень.
(Входная сериализация N-арного дерева представлена их обходом в порядке уровней, каждая группа дочерних узлов разделена значением null.)
Пример:
Input: root = [1,null,3,2,4,null,5,6]
Output: 3
Explanation: Diameter is shown in red color.
class Solution {
var diameter = 0
func height(_ node: Node?) -> Int {
guard let node = node else { return 0 }
if node.children.isEmpty { return 0 }
var maxHeight1 = 0, maxHeight2 = 0
for child in node.children {
let parentHeight = height(child) + 1
if parentHeight > maxHeight1 {
maxHeight2 = maxHeight1
maxHeight1 = parentHeight
} else if parentHeight > maxHeight2 {
maxHeight2 = parentHeight
}
let distance = maxHeight1 + maxHeight2
self.diameter = max(self.diameter, distance)
}
return maxHeight1
}
func diameter(_ root: Node?) -> Int {
self.diameter = 0
_ = height(root)
return diameter
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 750. Number Of Corner Rectangles
Дан указатель на начало односвязного списка и два целых числа left и right, где left <= right. Необходимо перевернуть узлы списка, начиная с позиции left и заканчивая позицией right, и вернуть измененный список.
Пример:
👨💻 Алгоритм:
1⃣ Пройдите по строкам матрицы. Для каждой пары строк, найдите все столбцы, где оба значения равны 1.
2⃣ Подсчитайте количество таких столбцов. Если их больше одного, то они образуют прямоугольники.
3⃣ Для каждой пары строк добавьте количество возможных прямоугольников в общий счетчик.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 750. Number Of Corner Rectangles
Дан указатель на начало односвязного списка и два целых числа left и right, где left <= right. Необходимо перевернуть узлы списка, начиная с позиции left и заканчивая позицией right, и вернуть измененный список.
Пример:
Input: grid = [[1,0,0,1,0],[0,0,1,0,1],[0,0,0,1,0],[1,0,1,0,1]]
Output: 1
func countCornerRectangles(_ grid: [[Int]]) -> Int {
var count = 0
for i in 0..<grid.count {
for j in i+1..<grid.count {
var numPairs = 0
for k in 0..<grid[0].count {
if grid[i][k] == 1 && grid[j][k] == 1 {
numPairs += 1
}
}
if numPairs > 1 {
count += numPairs * (numPairs - 1) / 2
}
}
}
return count
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 751. IP to CIDR
Дан указатель на начало односвязного списка и два целых числа left и right, где left <= right. Необходимо перевернуть узлы списка, начиная с позиции left и заканчивая позицией right, и вернуть измененный список.
Пример:
👨💻 Алгоритм:
1⃣ Преобразовать начальный IP-адрес в целое число.
2⃣ Пока количество оставшихся IP-адресов n больше нуля: Определить наибольший блок, который начинается с текущего IP-адреса и не превышает количество оставшихся IP-адресов. Добавить этот блок к результату. Увеличить текущий IP-адрес на размер блока. Уменьшить количество оставшихся IP-адресов n.
3⃣ Преобразовать блоки обратно в формат CIDR и вернуть их.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 751. IP to CIDR
Дан указатель на начало односвязного списка и два целых числа left и right, где left <= right. Необходимо перевернуть узлы списка, начиная с позиции left и заканчивая позицией right, и вернуть измененный список.
Пример:
Input: ip = "255.0.0.7", n = 10
Output: ["255.0.0.7/32","255.0.0.8/29","255.0.0.16/32"]
func ipToInt(_ ip: String) -> Int {
let parts = ip.split(separator: ".").map { Int($0)! }
return (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3]
}
func intToIp(_ num: Int) -> String {
return "\(num >> 24 & 255).\(num >> 16 & 255).\(num >> 8 & 255).\(num & 255)"
}
func cidr(_ ip: String, _ prefixLength: Int) -> String {
return "\(ip)/\(prefixLength)"
}
func findCidrBlocks(_ startIp: String, _ n: Int) -> [String] {
var start = ipToInt(startIp)
var result = [String]()
var n = n
while n > 0 {
var maxSize = 1
while maxSize <= start && maxSize <= n {
maxSize <<= 1
}
maxSize >>= 1
while start % maxSize != 0 {
maxSize >>= 1
}
result.append(cidr(intToIp(start), 32 - maxSize.bitLength + 1))
start += maxSize
n -= maxSize
}
return result
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 752. Open the Lock
Перед вами замок с 4 круглыми колесами. Каждое колесо имеет 10 слотов: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'. Колеса могут свободно вращаться и оборачиваться: например, мы можем повернуть "9" так, чтобы получился "0", или "0" так, чтобы получился "9". Каждый ход состоит из поворота одного колеса на один слот. Изначально замок начинается с '0000', строки, представляющей состояние 4 колес. Вам дан список тупиков, то есть если замок отобразит любой из этих кодов, колеса замка перестанут вращаться, и вы не сможете его открыть. Учитывая цель, представляющую значение колес, которое позволит отпереть замок, верните минимальное общее количество оборотов, необходимое для открытия замка, или -1, если это невозможно.
Пример:
👨💻 Алгоритм:
1⃣ Используйте алгоритм BFS для поиска кратчайшего пути от начального состояния '0000' до целевого состояния, избегая тупиков. Инициализируйте очередь с начальным состоянием '0000' и начальным шагом 0. Используйте множество для отслеживания посещенных состояний, чтобы избежать повторного посещения одного и того же состояния.
2⃣ Для каждого состояния в очереди: Проверьте все возможные переходы на следующий шаг, вращая каждое колесо на +1 и -1. Если найденное состояние является целевым, верните количество шагов. Если найденное состояние не является тупиком и не было посещено ранее, добавьте его в очередь и отметьте как посещенное.
3⃣ Если очередь пуста и целевое состояние не найдено, верните -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 752. Open the Lock
Перед вами замок с 4 круглыми колесами. Каждое колесо имеет 10 слотов: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'. Колеса могут свободно вращаться и оборачиваться: например, мы можем повернуть "9" так, чтобы получился "0", или "0" так, чтобы получился "9". Каждый ход состоит из поворота одного колеса на один слот. Изначально замок начинается с '0000', строки, представляющей состояние 4 колес. Вам дан список тупиков, то есть если замок отобразит любой из этих кодов, колеса замка перестанут вращаться, и вы не сможете его открыть. Учитывая цель, представляющую значение колес, которое позволит отпереть замок, верните минимальное общее количество оборотов, необходимое для открытия замка, или -1, если это невозможно.
Пример:
Input: deadends = ["0201","0101","0102","1212","2002"], target = "0202"
Output: 6
func openLock(_ deadends: [String], _ target: String) -> Int {
func neighbors(_ node: String) -> [String] {
var res = [String]()
let nodeArray = Array(node)
for i in 0..<4 {
var nodeChars = nodeArray
let x = Int(String(nodeChars[i]))!
for d in [-1, 1] {
let y = (x + d + 10) % 10
nodeChars[i] = Character(String(y))
res.append(String(nodeChars))
}
}
return res
}
let dead = Set(deadends)
var queue = [(String, Int)]()
queue.append(("0000", 0))
var visited = Set<String>()
visited.insert("0000")
while !queue.isEmpty {
let (node, steps) = queue.removeFirst()
if node == target {
return steps
}
if dead.contains(node) {
continue
}
for neighbor in neighbors(node) {
if !visited.contains(neighbor) {
visited.insert(neighbor)
queue.append((neighbor, steps + 1))
}
}
}
return -1
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
#medium
Задача: 753. Cracking the Safe
Имеется сейф, защищенный паролем. Пароль представляет собой последовательность из n цифр, каждая из которых может находиться в диапазоне [0, k - 1]. Сейф имеет особый способ проверки пароля. Например, правильный пароль - "345", а вы вводите "012345": после ввода 0 последние 3 цифры - "0", что неверно. После ввода 1 последние 3 цифры - "01", что неверно. После ввода 2 последние 3 цифры - "012", что неверно.
После ввода 3 последние 3 цифры - "123", что неверно. После ввода 4 последние 3 цифры - "234", что неверно. После ввода 5 последние 3 цифры - "345", что верно, и сейф разблокируется. Верните любую строку минимальной длины, которая разблокирует сейф на определенном этапе ввода.
Пример:
👨💻 Алгоритм:
1⃣ Создайте граф, где каждая вершина представляет собой строку длины n-1, а каждое ребро между двумя вершинами представляет собой добавление одной из цифр из диапазона [0, k-1].
2⃣ Используйте алгоритм Эйлерова пути или цикла для нахождения пути, который проходит через каждое ребро ровно один раз.
3⃣ Составьте итоговую строку, которая включает начальную вершину и все добавленные цифры.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 753. Cracking the Safe
Имеется сейф, защищенный паролем. Пароль представляет собой последовательность из n цифр, каждая из которых может находиться в диапазоне [0, k - 1]. Сейф имеет особый способ проверки пароля. Например, правильный пароль - "345", а вы вводите "012345": после ввода 0 последние 3 цифры - "0", что неверно. После ввода 1 последние 3 цифры - "01", что неверно. После ввода 2 последние 3 цифры - "012", что неверно.
После ввода 3 последние 3 цифры - "123", что неверно. После ввода 4 последние 3 цифры - "234", что неверно. После ввода 5 последние 3 цифры - "345", что верно, и сейф разблокируется. Верните любую строку минимальной длины, которая разблокирует сейф на определенном этапе ввода.
Пример:
Input: n = 1, k = 2
Output: "10"
func crackSafe(_ n: Int, _ k: Int) -> String {
var seen = Set<String>()
var result = [Character]()
func dfs(_ node: String) {
for x in 0..<k {
let neighbor = node + String(x)
if !seen.contains(neighbor) {
seen.insert(neighbor)
dfs(String(neighbor.dropFirst()))
result.append(Character(String(x)))
}
}
}
let startNode = String(repeating: "0", count: n - 1)
dfs(startNode)
return startNode + String(result)
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
#medium
Задача: 754. Reach a Number
Вы стоите в позиции 0 на бесконечной числовой прямой. В позиции target находится пункт назначения. Вы можете сделать некоторое количество ходов numMoves так, чтобы: на каждом ходу вы могли пойти либо налево, либо направо. Во время i-го хода (начиная с i == 1 до i == numMoves) вы делаете i шагов в выбранном направлении. Учитывая целое число target, верните минимальное количество ходов (т.е. минимальное numMoves), необходимое для достижения пункта назначения.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте переменную для текущей позиции (position) и счетчик шагов (steps).
2⃣ Используйте цикл, чтобы добавлять к position текущее количество шагов и увеличивать steps.
3⃣ Если position достигает или превышает target и разница между position и target четная, остановите цикл и верните steps.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 754. Reach a Number
Вы стоите в позиции 0 на бесконечной числовой прямой. В позиции target находится пункт назначения. Вы можете сделать некоторое количество ходов numMoves так, чтобы: на каждом ходу вы могли пойти либо налево, либо направо. Во время i-го хода (начиная с i == 1 до i == numMoves) вы делаете i шагов в выбранном направлении. Учитывая целое число target, верните минимальное количество ходов (т.е. минимальное numMoves), необходимое для достижения пункта назначения.
Пример:
Input: target = 2
Output: 3
func reachTarget(_ target: Int) -> Int {
var target = abs(target)
var position = 0
var steps = 0
while position < target || (position - target) % 2 != 0 {
steps += 1
position += steps
}
return steps
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 494. Target Sum
Вам дан массив целых чисел nums и целое число target.
Вы хотите создать выражение из nums, добавляя один из символов '+' или '-' перед каждым числом в nums, а затем объединяя все числа.
Например, если nums = [2, 1], вы можете добавить '+' перед 2 и '-' перед 1, а затем объединить их, чтобы получить выражение "+2-1".
Верните количество различных выражений, которые можно построить и которые оцениваются в target.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация и вызов рекурсивной функции
Создайте переменную для хранения количества решений (count). Вызовите рекурсивную функцию calculate с начальными параметрами (nums, начальный индекс 0, начальная сумма 0, и target).
2⃣ Рекурсивная функция calculate
Если текущий индекс равен длине массива, проверьте, равна ли текущая сумма значению target. Если да, увеличьте счетчик решений. В противном случае, вызовите функцию рекурсивно дважды: добавляя и вычитая текущее значение из суммы.
3⃣ Возврат результата
После завершения всех рекурсивных вызовов верните значение счетчика решений.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 494. Target Sum
Вам дан массив целых чисел nums и целое число target.
Вы хотите создать выражение из nums, добавляя один из символов '+' или '-' перед каждым числом в nums, а затем объединяя все числа.
Например, если nums = [2, 1], вы можете добавить '+' перед 2 и '-' перед 1, а затем объединить их, чтобы получить выражение "+2-1".
Верните количество различных выражений, которые можно построить и которые оцениваются в target.
Пример:
Input: nums = [1,1,1,1,1], target = 3
Output: 5
Explanation: There are 5 ways to assign symbols to make the sum of nums be target 3.
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3
Создайте переменную для хранения количества решений (count). Вызовите рекурсивную функцию calculate с начальными параметрами (nums, начальный индекс 0, начальная сумма 0, и target).
Если текущий индекс равен длине массива, проверьте, равна ли текущая сумма значению target. Если да, увеличьте счетчик решений. В противном случае, вызовите функцию рекурсивно дважды: добавляя и вычитая текущее значение из суммы.
После завершения всех рекурсивных вызовов верните значение счетчика решений.
class Solution {
var count = 0
func findTargetSumWays(_ nums: [Int], _ S: Int) -> Int {
calculate(nums, 0, 0, S)
return count
}
func calculate(_ nums: [Int], _ i: Int, _ sum: Int, _ S: Int) {
if i == nums.count {
if sum == S {
count += 1
}
} else {
calculate(nums, i + 1, sum + nums[i], S)
calculate(nums, i + 1, sum - nums[i], S)
}
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 443. String Compression
Дан массив символов 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.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 443. String Compression
Дан массив символов 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 {
func compress(_ chars: inout [Character]) -> Int {
var i = 0
var res = 0
while i < chars.count {
var groupLength = 1
while i + groupLength < chars.count && chars[i + groupLength] == chars[i] {
groupLength += 1
}
chars[res] = chars[i]
res += 1
if groupLength > 1 {
let strRepr = String(groupLength)
for ch in strRepr {
chars[res] = ch
res += 1
}
}
i += groupLength
}
return res
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 673. Number of Longest Increasing Subsequence
Дан массив целых чисел nums, верните количество самых длинных строго возрастающих подпоследовательностей.
Пример:
👨💻 Алгоритм:
1⃣ Объявите два массива динамического программирования length и count, и инициализируйте их значениями length[i]=1 и count[i]=1. Итерируйте i от 0 до n−1. Для каждого i итерируйте j от 0 до i−1 и, если nums[j] < nums[i], обновите length[i] и count[i] в зависимости от значений length[j] и count[j].
2⃣ Найдите максимальное значение в массиве length и сохраните его в переменной maxLength. Инициализируйте переменную result = 0.
3⃣ Итерируйте i от 0 до n−1 и, если length[i] = maxLength, добавьте count[i] к result. Верните result.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 673. Number of Longest Increasing Subsequence
Дан массив целых чисел nums, верните количество самых длинных строго возрастающих подпоследовательностей.
Пример:
Input: n = 1, presses = 1
Output: 2
Explanation: Status can be:
- [off] by pressing button 1
- [on] by pressing button 2
class Solution {
func findNumberOfLIS(_ nums: [Int]) -> Int {
let n = nums.count
var length = Array(repeating: 1, count: n)
var count = Array(repeating: 1, count: n)
for i in 0..<n {
for j in 0..<i {
if nums[j] < nums[i] {
if length[j] + 1 > length[i] {
length[i] = length[j] + 1
count[i] = 0
}
if length[j] + 1 == length[i] {
count[i] += count[j]
}
}
}
}
let maxLength = length.max() ?? 0
var result = 0
for i in 0..<n {
if length[i] == maxLength {
result += count[i]
}
}
return result
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 435. Non-overlapping Intervals
Дан массив интервалов intervals, где intervals[i] = [starti, endi]. Верните минимальное количество интервалов, которые нужно удалить, чтобы остальные интервалы не пересекались.
Пример:
👨💻 Алгоритм:
1⃣ Отсортируйте интервалы по времени окончания.
2⃣ Инициализируйте переменную ответа ans = 0 и целое число k для представления самого последнего времени окончания. k следует инициализировать небольшим значением, например, INT_MIN.
3⃣ Итеративно пройдитесь по интервалам. Для каждого интервала: Если время начала больше или равно k, обновите k до времени окончания текущего интервала. В противном случае увеличьте ans. Верните ans.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 435. Non-overlapping Intervals
Дан массив интервалов 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
#medium
Задача: 621. Task Scheduler
Вам дан массив задач процессора, каждая из которых представлена буквами от A до Z, и время охлаждения, n. Каждый цикл или интервал позволяет завершить одну задачу. Задачи могут быть выполнены в любом порядке, но есть ограничение: одинаковые задачи должны быть разделены не менее чем n интервалами из-за времени охлаждения. Верните минимальное количество интервалов, необходимое для выполнения всех задач.
Пример:
👨💻 Алгоритм:
1⃣ Подсчитайте количество каждой задачи и найдите максимальное количество вхождений (maxFreq).
2⃣ Вычислите количество интервалов, необходимых для задач с maxFreq: (maxFreq - 1) * (n + 1) + countMaxFreq, где countMaxFreq - количество задач, имеющих maxFreq.
3⃣ Верните максимум между вычисленным значением и длиной массива задач, поскольку некоторые задачи могут заполнять интервал до n.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 621. Task Scheduler
Вам дан массив задач процессора, каждая из которых представлена буквами от A до Z, и время охлаждения, n. Каждый цикл или интервал позволяет завершить одну задачу. Задачи могут быть выполнены в любом порядке, но есть ограничение: одинаковые задачи должны быть разделены не менее чем n интервалами из-за времени охлаждения. Верните минимальное количество интервалов, необходимое для выполнения всех задач.
Пример:
Input: tasks = ["A","A","A","B","B","B"], n = 2
Output: 8
func leastInterval(_ tasks: [Character], _ n: Int) -> Int {
var taskCounts = [Character: Int]()
for task in tasks {
taskCounts[task, default: 0] += 1
}
let maxFreq = taskCounts.values.max()!
let countMaxFreq = taskCounts.values.filter { $0 == maxFreq }.count
return max(tasks.count, (maxFreq - 1) * (n + 1) + countMaxFreq)
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 161. One Edit Distance
Даны две строки s и t. Верните true, если они отличаются ровно на одну операцию редактирования, иначе верните false.
Строка s считается отличающейся на одну операцию редактирования от строки t, если можно:
- Вставить ровно один символ в строку s, чтобы получить t.
- Удалить ровно один символ из строки s, чтобы получить t.
- Заменить ровно один символ в строке s на другой символ, чтобы получить t.
Пример:
👨💻 Алгоритм:
1⃣ Проверка длины строк:
Убедитесь, что строка s короче строки t. Если это не так, поменяйте их местами и повторите проверку.
Если разница в длине между s и t больше 1, то строки невозможно привести к равенству одной операцией редактирования, верните false.
2⃣ Сравнение строк посимвольно:
Проходите по строке s и сравнивайте каждый символ с соответствующим символом в строке t.
Если находите различающийся символ:
Если длины строк равны (ns == nt), проверьте, равны ли подстроки после текущего символа для обеих строк (s.substr(i + 1) == t.substr(i + 1)). Если равны, возвращайте true, иначе false.
Если длины строк различаются, проверьте, равна ли подстрока s начиная с текущего символа подстроке t начиная с следующего символа (s.substr(i) == t.substr(i + 1)). Если равны, возвращайте true, иначе false
3⃣ Проверка на возможное добавление символа в конец s:
Если после посимвольного сравнения не было найдено различий на всей длине s и t длиннее s на один символ, это означает, что t можно получить добавлением одного символа в конец s. В этом случае верните true.
В противном случае верните false, так как это означает, что t либо имеет больше отличий, либо такой же размер как s без возможности привести их к равенству одной операцией редактирования.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 161. One Edit Distance
Даны две строки s и t. Верните true, если они отличаются ровно на одну операцию редактирования, иначе верните false.
Строка s считается отличающейся на одну операцию редактирования от строки t, если можно:
- Вставить ровно один символ в строку s, чтобы получить t.
- Удалить ровно один символ из строки s, чтобы получить t.
- Заменить ровно один символ в строке s на другой символ, чтобы получить t.
Пример:
Input: s = "ab", t = "acb"
Output: true
Explanation: We can insert 'c' into s to get t.
Убедитесь, что строка s короче строки t. Если это не так, поменяйте их местами и повторите проверку.
Если разница в длине между s и t больше 1, то строки невозможно привести к равенству одной операцией редактирования, верните false.
Проходите по строке s и сравнивайте каждый символ с соответствующим символом в строке t.
Если находите различающийся символ:
Если длины строк равны (ns == nt), проверьте, равны ли подстроки после текущего символа для обеих строк (s.substr(i + 1) == t.substr(i + 1)). Если равны, возвращайте true, иначе false.
Если длины строк различаются, проверьте, равна ли подстрока s начиная с текущего символа подстроке t начиная с следующего символа (s.substr(i) == t.substr(i + 1)). Если равны, возвращайте true, иначе false
Если после посимвольного сравнения не было найдено различий на всей длине s и t длиннее s на один символ, это означает, что t можно получить добавлением одного символа в конец s. В этом случае верните true.
В противном случае верните false, так как это означает, что t либо имеет больше отличий, либо такой же размер как s без возможности привести их к равенству одной операцией редактирования.
class Solution {
func isOneEditDistance(_ s: String, _ t: String) -> Bool {
let ns = s.count
let nt = t.count
let sChars = Array(s)
let tChars = Array(t)
if ns > nt { return isOneEditDistance(t, s) }
if nt - ns > 1 { return false }
for i in 0..<ns {
if sChars[i] != tChars[i] {
if ns == nt { return String(sChars[(i + 1)...]) == String(tChars[(i + 1)...]) }
else { return String(sChars[i...]) == String(tChars[(i + 1)...]) }
}
}
return ns + 1 == nt
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM