#easy
Задача: 734. Sentence Similarity
Мы можем представить предложение в виде массива слов, например, предложение "I am happy with leetcode" можно представить как arr = ["I", "am",happy", "with", "leetcode"].
Даны два предложения sentence1 и sentence2, каждое из которых представлено в виде массива строк, и массив пар строк similarPairs, где similarPairs[i] = [xi, yi] указывает, что два слова xi и yi похожи. Возвращается true, если предложения sentence1 и sentence2 похожи, или false, если они не похожи. Два предложения похожи, если: у них одинаковая длина (т.е, Заметьте, что слово всегда похоже само на себя, также обратите внимание, что отношение сходства не является транзитивным. Например, если слова a и b похожи, а слова b и c похожи, то a и c не обязательно похожи.
Пример:
👨💻 Алгоритм:
1⃣ Проверьте, равны ли длины предложений sentence1 и sentence2. Если нет, верните false.
2⃣ Создайте словарь для хранения всех пар похожих слов.
3⃣ Проверьте каждую пару слов из предложений sentence1 и sentence2 на схожесть, используя словарь и правило, что слово всегда похоже на само себя.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 734. Sentence Similarity
Мы можем представить предложение в виде массива слов, например, предложение "I am happy with leetcode" можно представить как arr = ["I", "am",happy", "with", "leetcode"].
Даны два предложения sentence1 и sentence2, каждое из которых представлено в виде массива строк, и массив пар строк similarPairs, где similarPairs[i] = [xi, yi] указывает, что два слова xi и yi похожи. Возвращается true, если предложения sentence1 и sentence2 похожи, или false, если они не похожи. Два предложения похожи, если: у них одинаковая длина (т.е, Заметьте, что слово всегда похоже само на себя, также обратите внимание, что отношение сходства не является транзитивным. Например, если слова a и b похожи, а слова b и c похожи, то a и c не обязательно похожи.
Пример:
Input: sentence1 = ["great","acting","skills"], sentence2 = ["fine","drama","talent"], similarPairs = [["great","fine"],["drama","acting"],["skills","talent"]]
Output: true
func areSentencesSimilar(_ sentence1: [String], _ sentence2: [String], _ similarPairs: [[String]]) -> Bool {
if sentence1.count != sentence2.count {
return false
}
var similar = [String: Set<String>]()
for pair in similarPairs {
let (x, y) = (pair[0], pair[1])
if similar[x] == nil {
similar[x] = Set<String>()
}
if similar[y] == nil {
similar[y] = Set<String>()
}
similar[x]!.insert(y)
similar[y]!.insert(x)
}
for (w1, w2) in zip(sentence1, sentence2) {
if w1 != w2 && (similar[w1] == nil || !similar[w1]!.contains(w2)) {
return false
}
}
return true
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 735. Asteroid Collision
Нам дан массив asteroids, состоящий из целых чисел, представляющих астероиды в ряд. Для каждого астероида абсолютное значение обозначает его размер, а знак - направление движения (положительное - вправо, отрицательное - влево). Каждый астероид движется с одинаковой скоростью. Определите состояние астероидов после всех столкновений. Если два астероида столкнутся, меньший из них взорвется. Если оба одинакового размера, то взорвутся оба. Два астероида, движущиеся в одном направлении, никогда не встретятся.
Пример:
👨💻 Алгоритм:
1⃣ Используйте стек для отслеживания движущихся вправо астероидов.
2⃣ Пройдите по массиву астероидов: Если астероид движется вправо, добавьте его в стек. Если астероид движется влево, сравните его с последним астероидом в стеке (если он есть и движется вправо): Если движущийся вправо астероид больше, текущий взорвется. Если движущийся влево астероид больше, последний астероид в стеке взорвется, и продолжите сравнение. Если они одинакового размера, оба взорвутся.
3⃣ Добавьте оставшиеся астероиды из стека и текущий астероид в результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 735. Asteroid Collision
Нам дан массив asteroids, состоящий из целых чисел, представляющих астероиды в ряд. Для каждого астероида абсолютное значение обозначает его размер, а знак - направление движения (положительное - вправо, отрицательное - влево). Каждый астероид движется с одинаковой скоростью. Определите состояние астероидов после всех столкновений. Если два астероида столкнутся, меньший из них взорвется. Если оба одинакового размера, то взорвутся оба. Два астероида, движущиеся в одном направлении, никогда не встретятся.
Пример:
Input: sentence1 = ["great","acting","skills"], sentence2 = ["fine","drama","talent"], similarPairs = [["great","fine"],["drama","acting"],["skills","talent"]]
Output: true
func asteroidCollision(_ asteroids: [Int]) -> [Int] {
var stack = [Int]()
for asteroid in asteroids {
var alive = true
while alive && asteroid < 0 && !stack.isEmpty && stack.last! > 0 {
let last = stack.removeLast()
if last == -asteroid {
alive = false
} else if last > -asteroid {
stack.append(last)
alive = false
}
}
if alive {
stack.append(asteroid)
}
}
return stack
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 736. Parse Lisp Expression
Нам дан массив asteroids, состоящий из целых чисел, представляющих астероиды в ряд. Для каждого астероида абсолютное значение обозначает его размер, а знак - направление движения (положительное - вправо, отрицательное - влево). Каждый астероид движется с одинаковой скоростью. Определите состояние астероидов после всех столкновений. Если два астероида столкнутся, меньший из них взорвется. Если оба одинакового размера, то взорвутся оба. Два астероида, движущиеся в одном направлении, никогда не встретятся.
Пример:
👨💻 Алгоритм:
1⃣ Определите функцию для оценки выражений.
2⃣ Используйте рекурсивный подход для обработки различных типов выражений (let, add, mult, и переменных).
3⃣ Используйте словарь для отслеживания значений переменных с учетом области видимости.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 736. Parse Lisp Expression
Нам дан массив asteroids, состоящий из целых чисел, представляющих астероиды в ряд. Для каждого астероида абсолютное значение обозначает его размер, а знак - направление движения (положительное - вправо, отрицательное - влево). Каждый астероид движется с одинаковой скоростью. Определите состояние астероидов после всех столкновений. Если два астероида столкнутся, меньший из них взорвется. Если оба одинакового размера, то взорвутся оба. Два астероида, движущиеся в одном направлении, никогда не встретятся.
Пример:
Input: expression = "(let x 2 (mult x (let x 3 y 4 (add x y))))"
Output: 14
class Solution {
func evaluate(_ expression: String) -> Int {
func evaluate(_ expression: String, _ env: inout [String: Int]) -> Int {
if expression.first != "(" {
if let val = Int(expression) {
return val
}
return env[expression]!
}
var tokens = tokenize(expression)
if tokens[0] == "let" {
for i in stride(from: 1, to: tokens.count - 2, by: 2) {
env[tokens[i]] = evaluate(tokens[i + 1], &env)
}
return evaluate(tokens.last!, &env)
} else if tokens[0] == "add" {
return evaluate(tokens[1], &env) + evaluate(tokens[2], &env)
} else if tokens[0] == "mult" {
return evaluate(tokens[1], &env) * evaluate(tokens[2], &env)
}
return 0
}
func tokenize(_ expression: String) -> [String] {
var tokens: [String] = []
var token: String = ""
var parens: Int = 0
for char in expression {
if char == "(" {
parens += 1
if parens == 1 {
continue
}
} else if char == ")" {
parens -= 1
if parens == 0 {
tokens.append(tokenize(token))
token = ""
continue
}
} else if char == " " && parens == 1 {
if !token.isEmpty {
tokens.append(token)
token = ""
}
continue
}
token.append(char)
}
if !token.isEmpty {
tokens.append(token)
}
return tokens
}
var env: [String: Int] = [:]
return evaluate(expression, &env)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#medium
Задача: 737. Sentence Similarity II
Мы можем представить предложение в виде массива слов, например, предложение "I am happy with leetcode" можно представить как arr = ["I", "am",happy", "with", "leetcode"].
Даны два предложения sentence1 и sentence2, каждое из которых представлено в виде массива строк, и массив пар строк similarPairs, где similarPairs[i] = [xi, yi] указывает, что два слова xi и yi похожи. Возвращается true, если предложения sentence1 и sentence2 похожи, или false, если они не похожи. Два предложения похожи, если: у них одинаковая длина (т.е, Заметьте, что слово всегда похоже само на себя, также обратите внимание, что отношение сходства является транзитивным. Например, если слова a и b похожи, а слова b и c похожи, то a и c похожи.
Пример:
👨💻 Алгоритм:
1⃣ Проверить, одинаковой ли длины предложения sentence1 и sentence2. Если нет, вернуть false.
2⃣ Построить граф схожести слов с использованием словаря.
3⃣ Использовать поиск в глубину (DFS) для проверки транзитивной схожести слов в предложениях.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 737. Sentence Similarity II
Мы можем представить предложение в виде массива слов, например, предложение "I am happy with leetcode" можно представить как arr = ["I", "am",happy", "with", "leetcode"].
Даны два предложения sentence1 и sentence2, каждое из которых представлено в виде массива строк, и массив пар строк similarPairs, где similarPairs[i] = [xi, yi] указывает, что два слова xi и yi похожи. Возвращается true, если предложения sentence1 и sentence2 похожи, или false, если они не похожи. Два предложения похожи, если: у них одинаковая длина (т.е, Заметьте, что слово всегда похоже само на себя, также обратите внимание, что отношение сходства является транзитивным. Например, если слова a и b похожи, а слова b и c похожи, то a и c похожи.
Пример:
Input: sentence1 = ["great","acting","skills"], sentence2 = ["fine","drama","talent"], similarPairs = [["great","good"],["fine","good"],["drama","acting"],["skills","talent"]]
Output: true
func areSentencesSimilar(_ sentence1: [String], _ sentence2: [String], _ similarPairs: [[String]]) -> Bool {
if sentence1.count != sentence2.count {
return false
}
var graph = [String: [String]]()
for pair in similarPairs {
let (x, y) = (pair[0], pair[1])
graph[x, default: []].append(y)
graph[y, default: []].append(x)
}
func dfs(_ word1: String, _ word2: String, _ visited: inout Set<String>) -> Bool {
if word1 == word2 {
return true
}
visited.insert(word1)
for neighbor in graph[word1, default: []] {
if !visited.contains(neighbor) && dfs(neighbor, word2, &visited) {
return true
}
}
return false
}
for (w1, w2) in zip(sentence1, sentence2) {
if w1 != w2 {
var visited = Set<String>()
if !dfs(w1, w2, &visited) {
return false
}
}
}
return true
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#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
#hard
Задача: 741. Cherry Pickup
Вам дана сетка n x n, представляющая поле вишен. Каждая клетка - одно из трех возможных целых чисел. 0 означает, что клетка пуста, и вы можете пройти через нее, 1 означает, что клетка содержит вишню, которую вы можете сорвать и пройти через нее, или -1 означает, что клетка содержит шип, который преграждает вам путь. Верните максимальное количество вишен, которое вы можете собрать, следуя следующим правилам: Начиная с позиции (0, 0) и достигая (n - 1, n - 1) путем перемещения вправо или вниз через допустимые клетки пути (клетки со значением 0 или 1).
После достижения (n - 1, n - 1) вернитесь в (0, 0), двигаясь влево или вверх по клеткам с действительными путями. Проходя через клетку пути, содержащую вишню, вы поднимаете ее, и клетка становится пустой клеткой 0. Если между (0, 0) и (n - 1, n - 1) нет действительного пути, то вишни собрать нельзя.
Пример:
👨💻 Алгоритм:
1⃣ Используйте динамическое программирование для подсчета максимального количества вишен, которые можно собрать при движении от (0, 0) до (n - 1, n - 1).
2⃣ Примените еще один проход с использованием динамического программирования для движения обратно от (n - 1, n - 1) до (0, 0), чтобы учитывать вишни, собранные на обратном пути.
3⃣ Объедините результаты двух проходов, чтобы найти максимальное количество вишен, которые можно собрать.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 741. Cherry Pickup
Вам дана сетка n x n, представляющая поле вишен. Каждая клетка - одно из трех возможных целых чисел. 0 означает, что клетка пуста, и вы можете пройти через нее, 1 означает, что клетка содержит вишню, которую вы можете сорвать и пройти через нее, или -1 означает, что клетка содержит шип, который преграждает вам путь. Верните максимальное количество вишен, которое вы можете собрать, следуя следующим правилам: Начиная с позиции (0, 0) и достигая (n - 1, n - 1) путем перемещения вправо или вниз через допустимые клетки пути (клетки со значением 0 или 1).
После достижения (n - 1, n - 1) вернитесь в (0, 0), двигаясь влево или вверх по клеткам с действительными путями. Проходя через клетку пути, содержащую вишню, вы поднимаете ее, и клетка становится пустой клеткой 0. Если между (0, 0) и (n - 1, n - 1) нет действительного пути, то вишни собрать нельзя.
Пример:
Input: grid = [[0,1,-1],[1,0,-1],[1,1,1]]
Output: 5
func cherryPickup(_ grid: [[Int]]) -> Int {
let n = grid.count
var dp = Array(repeating: Array(repeating: Array(repeating: Int.min, count: n), count: n), count: n)
dp[0][0][0] = grid[0][0]
for k in 1...(2 * (n - 1)) {
for i1 in max(0, k - n + 1)...min(n - 1, k) {
for i2 in max(0, k - n + 1)...min(n - 1, k) {
let j1 = k - i1
let j2 = k - i2
if j1 < n && j2 < n && grid[i1][j1] != -1 && grid[i2][j2] != -1 {
var maxCherries = Int.min
if i1 > 0 && i2 > 0 { maxCherries = max(maxCherries, dp[i1 - 1][i2 - 1][k - 1]) }
if i1 > 0 { maxCherries = max(maxCherries, dp[i1 - 1][i2][k - 1]) }
if i2 > 0 { maxCherries = max(maxCherries, dp[i1][i2 - 1][k - 1]) }
maxCherries = max(maxCherries, dp[i1][i2][k - 1])
if maxCherries != Int.min {
dp[i1][i2][k] = maxCherries + grid[i1][j1]
if i1 != i2 { dp[i1][i2][k] += grid[i2][j2] }
}
}
}
}
}
return max(0, dp[n - 1][n - 1][2 * (n - 1)])
}Ставь 👍 и забирай 📚 Базу знаний
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
#easy
Задача: 744. Find Smallest Letter Greater Than Target
Нам дан массив символов letters, отсортированный в неубывающем порядке, и символ target. В массиве letters есть как минимум два разных символа. Возвращается наименьший символ в letters, который лексикографически больше target. Если такого символа не существует, возвращается первый символ в буквах.
Пример:
👨💻 Алгоритм:
1⃣ Использовать бинарный поиск для нахождения позиции первого символа в letters, который лексикографически больше target.
2⃣ Если найденный символ существует, вернуть его.
3⃣ Если такого символа не существует, вернуть первый символ в letters.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 744. Find Smallest Letter Greater Than Target
Нам дан массив символов letters, отсортированный в неубывающем порядке, и символ target. В массиве letters есть как минимум два разных символа. Возвращается наименьший символ в letters, который лексикографически больше target. Если такого символа не существует, возвращается первый символ в буквах.
Пример:
Input: letters = ["c","f","j"], target = "a"
Output: "c"
func nextGreatestLetter(_ letters: [Character], _ target: Character) -> Character {
var left = 0
var right = letters.count - 1
while left <= right {
let mid = (left + right) / 2
if letters[mid] > target {
right = mid - 1
} else {
left = mid + 1
}
}
return letters[left % letters.count]
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#hard
Задача: 745. Prefix and Suffix Search
Создайте специальный словарь, в котором поиск слов осуществляется по префиксу и суффиксу. Реализуйте класс WordFilter: WordFilter(string[] words) Инициализирует объект со словами в словаре. f(string pref, string suff) Возвращает индекс слова в словаре, которое имеет префикс pref и суффикс suff. Если существует более одного допустимого индекса, возвращается наибольший из них. Если в словаре нет такого слова, возвращается -1.
Пример:
👨💻 Алгоритм:
1⃣ Сохраните слова и их индексы в словаре.
2⃣ Создайте объединенные ключи, состоящие из префиксов и суффиксов для всех возможных комбинаций.
3⃣ Реализуйте функцию поиска, которая ищет наибольший индекс слова по префиксу и суффиксу.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 745. Prefix and Suffix Search
Создайте специальный словарь, в котором поиск слов осуществляется по префиксу и суффиксу. Реализуйте класс WordFilter: WordFilter(string[] words) Инициализирует объект со словами в словаре. f(string pref, string suff) Возвращает индекс слова в словаре, которое имеет префикс pref и суффикс suff. Если существует более одного допустимого индекса, возвращается наибольший из них. Если в словаре нет такого слова, возвращается -1.
Пример:
Input: letters = ["c","f","j"], target = "a"
Output: "c"
class WordFilter {
private var prefixSuffixMap = [String: Int]()
init(_ words: [String]) {
for (index, word) in words.enumerated() {
let length = word.count
for prefixLength in 1...length {
for suffixLength in 1...length {
let prefix = String(word.prefix(prefixLength))
let suffix = String(word.suffix(suffixLength))
let key = prefix + "#" + suffix
prefixSuffixMap[key] = index
}
}
}
}
func f(_ pref: String, _ suff: String) -> Int {
let key = pref + "#" + suff
return prefixSuffixMap[key, default: -1]
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#easy
Задача: 746. Min Cost Climbing Stairs
Вам дан целочисленный массив cost, где cost[i] - стоимость i-й ступеньки на лестнице. После оплаты стоимости вы можете подняться на одну или две ступеньки. Вы можете начать со ступеньки с индексом 0 или со ступеньки с индексом 1. Верните минимальную стоимость достижения вершины этажа.
Пример:
👨💻 Алгоритм:
1⃣ Создать массив dp, где dp[i] хранит минимальную стоимость достижения i-й ступеньки.
2⃣ Инициализировать dp[0] и dp[1] как cost[0] и cost[1] соответственно. Заполнить dp используя минимальную стоимость подъема с предыдущих ступенек.
3⃣ Вернуть минимальную стоимость достижения вершины.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 746. Min Cost Climbing Stairs
Вам дан целочисленный массив cost, где cost[i] - стоимость i-й ступеньки на лестнице. После оплаты стоимости вы можете подняться на одну или две ступеньки. Вы можете начать со ступеньки с индексом 0 или со ступеньки с индексом 1. Верните минимальную стоимость достижения вершины этажа.
Пример:
Input: cost = [10,15,20]
Output: 15
func minCostClimbingStairs(_ cost: [Int]) -> Int {
var dp = cost
for i in 2..<cost.count {
dp[i] += min(dp[i - 1], dp[i - 2])
}
return min(dp[cost.count - 1], dp[cost.count - 2])
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
#easy
Задача: 747. Largest Number At Least Twice of Others
Вам дан целочисленный массив nums, в котором наибольшее целое число уникально. Определите, является ли наибольший элемент массива по крайней мере в два раза больше всех остальных чисел в массиве. Если да, то верните индекс самого большого элемента, в противном случае верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Найдите максимальный элемент в массиве и его индекс.
2⃣ Проверьте, является ли этот максимальный элемент по крайней мере в два раза больше всех остальных элементов массива.
3⃣ Если условие выполняется, верните индекс максимального элемента, иначе верните -1.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 747. Largest Number At Least Twice of Others
Вам дан целочисленный массив nums, в котором наибольшее целое число уникально. Определите, является ли наибольший элемент массива по крайней мере в два раза больше всех остальных чисел в массиве. Если да, то верните индекс самого большого элемента, в противном случае верните -1.
Пример:
Input: nums = [3,6,1,0]
Output: 1
func dominantIndex(_ nums: [Int]) -> Int {
guard let maxVal = nums.max() else { return -1 }
let maxIndex = nums.firstIndex(of: maxVal)!
for num in nums {
if num != maxVal && maxVal < 2 * num {
return -1
}
}
return maxIndex
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
😁2
#easy
Задача: 748. Shortest Completing Word
Вам дан целочисленный массив nums, в котором наибольшее целое число уникально. Определите, является ли наибольший элемент массива по крайней мере в два раза больше всех остальных чисел в массиве. Если да, то верните индекс самого большого элемента, в противном случае верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Извлечь все буквы из licensePlate, игнорируя цифры и пробелы, и создать словарь для подсчета частоты каждой буквы.
2⃣ Пройти по массиву words, проверяя каждое слово на соответствие требованиям.
3⃣ Найти самое короткое завершающее слово среди подходящих.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 748. Shortest Completing Word
Вам дан целочисленный массив nums, в котором наибольшее целое число уникально. Определите, является ли наибольший элемент массива по крайней мере в два раза больше всех остальных чисел в массиве. Если да, то верните индекс самого большого элемента, в противном случае верните -1.
Пример:
Input: licensePlate = "1s3 PSt", words = ["step","steps","stripe","stepple"]
Output: "steps"
func shortestCompletingWord(_ licensePlate: String, _ words: [String]) -> String {
func getCharCount(_ s: String) -> [Character: Int] {
var count = [Character: Int]()
for char in s.lowercased() {
if char.isLetter {
count[char, default: 0] += 1
}
}
return count
}
let licenseCount = getCharCount(licensePlate)
func isCompletingWord(_ word: String, _ licenseCount: [Character: Int]) -> Bool {
var wordCount = [Character: Int]()
for char in word {
wordCount[char, default: 0] += 1
}
for (char, cnt) in licenseCount {
if wordCount[char, default: 0] < cnt {
return false
}
}
return true
}
var result: String?
for word in words {
if isCompletingWord(word, licenseCount) {
if result == nil || word.count < result!.count {
result = word
}
}
}
return result!
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
#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
#easy
Задача: 1523. Count Odd Numbers in an Interval Range
### Условие задачи
Даны два неотрицательных целых числа low и high. Верните количество нечётных чисел между low и high (включительно).
Пример:
👨💻 Алгоритм:
1⃣ Проверьте, является ли число low нечётным. Это можно легко сделать с помощью оператора %, но мы используем побитовый оператор &, так как он более эффективен.
2⃣ Если low нечётное, увеличьте его на 1.
3⃣ Верните (high - low) / 2 + 1. Важный момент здесь - проверить, не стало ли low больше, чем high после увеличения. Это произойдёт, если low = high, и в этом случае следует вернуть 0.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Задача: 1523. Count Odd Numbers in an Interval Range
### Условие задачи
Даны два неотрицательных целых числа low и high. Верните количество нечётных чисел между low и high (включительно).
Пример:
Input: low = 3, high = 7
Output: 3
Explanation: The odd numbers between 3 and 7 are [3,5,7].
class Solution {
func countOdds(_ low: Int, _ high: Int) -> Int {
var low = low
if (low & 1) == 0 {
low += 1
}
return low > high ? 0 : (high - low) / 2 + 1
}
}Ставь 👍 и забирай 📚 Базу знаний
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