Задача: 79. Word Search
Сложность: medium
Дана сетка символов размером m на n, называемая board, и строка word. Верните true, если слово word существует в сетке.
Слово можно составить из букв последовательно смежных ячеек, где смежные ячейки находятся рядом по горизонтали или вертикали. Одна и та же ячейка с буквой не может быть использована более одного раза.
Пример:
👨💻 Алгоритм:
1⃣ Общий подход к алгоритмам обратной трассировки: В каждом алгоритме обратной трассировки существует определенный шаблон кода. Например, один из таких шаблонов можно найти в нашем разделе "Рекурсия II". Скелет алгоритма представляет собой цикл, который проходит через каждую ячейку в сетке. Для каждой ячейки вызывается функция обратной трассировки (backtrack()), чтобы проверить, можно ли найти решение, начиная с этой ячейки.
2⃣ Функция обратной трассировки: Эта функция, реализуемая как алгоритм поиска в глубину (DFS), часто представляет собой рекурсивную функцию. Первым делом проверяется, достигнут ли базовый случай рекурсии, когда слово для сопоставления пусто, то есть для каждого префикса слова уже найдено совпадение. Затем проверяется, не является ли текущее состояние недопустимым: либо позиция ячейки выходит за границы доски, либо буква в текущей ячейке не совпадает с первой буквой слова.
3⃣ Исследование и завершение: Если текущий шаг допустим, начинается исследование с использованием стратегии DFS. Сначала текущая ячейка помечается как посещенная, например, любой неалфавитный символ подойдет. Затем осуществляется итерация через четыре возможных направления: вверх, вправо, вниз и влево. Порядок направлений может быть изменен по предпочтениям пользователя. В конце исследования ячейка возвращается к своему исходному состоянию, и возвращается результат исследования.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дана сетка символов размером m на n, называемая board, и строка word. Верните true, если слово word существует в сетке.
Слово можно составить из букв последовательно смежных ячеек, где смежные ячейки находятся рядом по горизонтали или вертикали. Одна и та же ячейка с буквой не может быть использована более одного раза.
Пример:
Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
Output: true
func exist(_ board: inout [[Character]], _ word: String) -> Bool {
let rows = board.count
let cols = board[0].count
func backtrack(_ row: Int, _ col: Int, _ index: Int) -> Bool {
if index == word.count { return true }
if row < 0 || row >= rows || col < 0 || col >= cols || board[row][col] != word[word.index(word.startIndex, offsetBy: index)] {
return false
}
board[row][col] = "#"
let directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
var result = false
for (rowOffset, colOffset) in directions {
result = backtrack(row + rowOffset, col + colOffset, index + 1)
if result { break }
}
board[row][col] = word[word.index(word.startIndex, offsetBy: index)]
return result
}
for row in 0..<rows {
for col in 0..<cols {
if backtrack(row, col, 0) { return true }
}
}
return false
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1256. Encode Number
Сложность: medium
Даны список слов, список отдельных букв (могут повторяться) и оценка каждого символа. Верните максимальную оценку любого правильного набора слов, образованного с помощью заданных букв (words[i] не может быть использовано два или более раз). Не обязательно использовать все символы в буквах, каждая буква может быть использована только один раз. Оценка букв 'a', 'b', 'c', ... , 'z' задаются значениями score[0], score[1], ... , score[25] соответственно.
Пример:
👨💻 Алгоритм:
1⃣ На основе предоставленной таблицы можно выявить закономерность для преобразования целого числа n в строку f(n)
2⃣ Из таблицы видно, что последовательность строк соответствует последовательности чисел в двоичной системе счисления за исключением начального значения n = 0.
3⃣ Таким образом, можно вывести, что:
Для каждого значения n > 0, функция f(n) представляет собой двоичное представление числа (n - 1).
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Даны список слов, список отдельных букв (могут повторяться) и оценка каждого символа. Верните максимальную оценку любого правильного набора слов, образованного с помощью заданных букв (words[i] не может быть использовано два или более раз). Не обязательно использовать все символы в буквах, каждая буква может быть использована только один раз. Оценка букв 'a', 'b', 'c', ... , 'z' задаются значениями score[0], score[1], ... , score[25] соответственно.
Пример:
Input: num = 23
Output: "1000"
Для каждого значения n > 0, функция f(n) представляет собой двоичное представление числа (n - 1).
class Solution {
func encode(_ num: Int) -> String {
if num == 0 { return "" }
return String(num - 1, radix: 2)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 274. H-Index
Сложность: medium
Дан массив целых чисел citations, где citations[i] — количество цитирований, которое исследователь получил за свою i-ю статью. Верните h-индекс исследователя.
Согласно определению h-индекса на Википедии: h-индекс определяется как максимальное значение h, такое что данный исследователь опубликовал по крайней мере h статей, каждая из которых была процитирована как минимум h раз.
Пример:
👨💻 Алгоритм:
1⃣ Отсортировать массив цитирований по убыванию:
Отсортировать массив citations в порядке убывания, чтобы наибольшее количество цитирований было в начале массива.
2⃣ Найти наибольшее значение i, для которого citations[i] > i:
Пройтись по отсортированному массиву и найти наибольшее значение i, для которого выполняется условие citations[i] > i.
Это значение будет индексом, при котором количество цитирований статьи больше индекса.
3⃣ Рассчитать h-индекс:
h-индекс будет равен i + 1, где i - наибольшее значение, найденное на предыдущем шаге.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив целых чисел citations, где citations[i] — количество цитирований, которое исследователь получил за свою i-ю статью. Верните h-индекс исследователя.
Согласно определению h-индекса на Википедии: h-индекс определяется как максимальное значение h, такое что данный исследователь опубликовал по крайней мере h статей, каждая из которых была процитирована как минимум h раз.
Пример:
Input: citations = [3,0,6,1,5]
Output: 3
Explanation: [3,0,6,1,5] means the researcher has 5 papers in total and each of them had received 3, 0, 6, 1, 5 citations respectively.
Since the researcher has 3 papers with at least 3 citations each and the remaining two with no more than 3 citations each, their h-index is 3.
Отсортировать массив citations в порядке убывания, чтобы наибольшее количество цитирований было в начале массива.
Пройтись по отсортированному массиву и найти наибольшее значение i, для которого выполняется условие citations[i] > i.
Это значение будет индексом, при котором количество цитирований статьи больше индекса.
h-индекс будет равен i + 1, где i - наибольшее значение, найденное на предыдущем шаге.
class Solution {
func hIndex(_ citations: [Int]) -> Int {
let n = citations.count
var papers = [Int](repeating: 0, count: n + 1)
for c in citations {
papers[min(n, c)] += 1
}
var k = n
var s = papers[n]
while k > s {
k -= 1
s += papers[k]
}
return k
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 622. Design Circular Queue
Сложность: medium
Разработайте свою реализацию круговой очереди. Круговая очередь - это линейная структура данных, в которой операции выполняются по принципу FIFO (First In First Out), а последняя позиция соединяется с первой, образуя круг. Одно из преимуществ круговой очереди заключается в том, что мы можем использовать пространство перед очередью. В обычной очереди, когда очередь становится полной, мы не можем вставить следующий элемент, даже если перед очередью есть свободное место. Но с помощью круговой очереди мы можем использовать пространство для хранения новых значений. Реализация класса MyCircularQueue: MyCircularQueue(k) Инициализирует объект с размером очереди k. int Front() Получает первый элемент из очереди. Если очередь пуста, возвращается -1. int Rear() Получает последний элемент из очереди. Если очередь пуста, возвращается -1. boolean enQueue(int value) Вставляет элемент в циклическую очередь. Возвращает true, если операция прошла успешно. boolean deQueue() Удаляет элемент из круговой очереди. Возвращает true, если операция выполнена успешно. boolean isEmpty() Проверяет, пуста ли круговая очередь. boolean isFull() Проверяет, заполнена ли круговая очередь. Вы должны решить проблему без использования встроенной структуры данных очереди в вашем языке программирования.
Пример:
👨💻 Алгоритм:
1⃣ Используйте массив фиксированного размера для хранения элементов очереди и два указателя: front для отслеживания начала очереди и rear для отслеживания конца очереди.
2⃣ Реализуйте методы enQueue и deQueue для вставки и удаления элементов, обновляя указатели по круговому принципу.
3⃣ Реализуйте методы Front, Rear, isEmpty и isFull для доступа к элементам и проверки состояния очереди.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Разработайте свою реализацию круговой очереди. Круговая очередь - это линейная структура данных, в которой операции выполняются по принципу FIFO (First In First Out), а последняя позиция соединяется с первой, образуя круг. Одно из преимуществ круговой очереди заключается в том, что мы можем использовать пространство перед очередью. В обычной очереди, когда очередь становится полной, мы не можем вставить следующий элемент, даже если перед очередью есть свободное место. Но с помощью круговой очереди мы можем использовать пространство для хранения новых значений. Реализация класса MyCircularQueue: MyCircularQueue(k) Инициализирует объект с размером очереди k. int Front() Получает первый элемент из очереди. Если очередь пуста, возвращается -1. int Rear() Получает последний элемент из очереди. Если очередь пуста, возвращается -1. boolean enQueue(int value) Вставляет элемент в циклическую очередь. Возвращает true, если операция прошла успешно. boolean deQueue() Удаляет элемент из круговой очереди. Возвращает true, если операция выполнена успешно. boolean isEmpty() Проверяет, пуста ли круговая очередь. boolean isFull() Проверяет, заполнена ли круговая очередь. Вы должны решить проблему без использования встроенной структуры данных очереди в вашем языке программирования.
Пример:
Input
["MyCircularQueue", "enQueue", "enQueue", "enQueue", "enQueue", "Rear", "isFull", "deQueue", "enQueue", "Rear"]
[[3], [1], [2], [3], [4], [], [], [], [4], []]
Output
[null, true, true, true, false, 3, true, true, true, 4]
class MyCircularQueue {
private var queue: [Int]
private var front: Int
private var rear: Int
private var size: Int
private var capacity: Int
init(_ k: Int) {
self.queue = Array(repeating: -1, count: k)
self.front = 0
self.rear = -1
self.size = 0
self.capacity = k
}
func enQueue(_ value: Int) -> Bool {
if isFull() {
return false
}
rear = (rear + 1) % capacity
queue[rear] = value
size += 1
return true
}
func deQueue() -> Bool {
if isEmpty() {
return false
}
front = (front + 1) % capacity
size -= 1
return true
}
func Front() -> Int {
return isEmpty() ? -1 : queue[front]
}
func Rear() -> Int {
return isEmpty() ? -1 : queue[rear]
}
func isEmpty() -> Bool {
return size == 0
}
func isFull() -> Bool {
return size == capacity
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 738. Monotone Increasing Digits
Сложность: medium
Целое число имеет монотонно возрастающие цифры тогда и только тогда, когда каждая пара соседних цифр x и y удовлетворяет x <= y. Задав целое число n, верните наибольшее число, которое меньше или равно n с монотонно возрастающими цифрами.
Пример:
👨💻 Алгоритм:
1⃣ Преобразуйте число в строку для удобства обработки.
2⃣ Найдите позицию, где последовательность перестает быть монотонной.
3⃣ Уменьшите соответствующую цифру и установите все последующие цифры в 9.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Целое число имеет монотонно возрастающие цифры тогда и только тогда, когда каждая пара соседних цифр 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
Задача: 367. Valid Perfect Square
Сложность: hard
Дано положительное целое число num, вернуть true, если num является идеальным квадратом, или false в противном случае.
Идеальный квадрат — это целое число, являющееся квадратом целого числа. Другими словами, это произведение некоторого целого числа на само себя.
Вы не должны использовать какие-либо встроенные библиотечные функции, такие как sqrt.
Пример:
👨💻 Алгоритм:
1⃣ Если num < 2, вернуть True. Установить левую границу в 2, а правую границу в num / 2.
2⃣ Пока left <= right, взять x = (left + right) / 2, вычислить guess_squared = x * x и сравнить его с num:
Если guess_squared == num, вернуть True.
Если guess_squared > num, сдвинуть правую границу right = x - 1.
В противном случае сдвинуть левую границу left = x + 1.
3⃣ Если вышли из цикла, вернуть False.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Дано положительное целое число num, вернуть true, если num является идеальным квадратом, или false в противном случае.
Идеальный квадрат — это целое число, являющееся квадратом целого числа. Другими словами, это произведение некоторого целого числа на само себя.
Вы не должны использовать какие-либо встроенные библиотечные функции, такие как sqrt.
Пример:
Input: num = 16
Output: true
Explanation: We return true because 4 * 4 = 16 and 4 is an integer.
Если guess_squared == num, вернуть True.
Если guess_squared > num, сдвинуть правую границу right = x - 1.
В противном случае сдвинуть левую границу left = x + 1.
class Solution {
func isPerfectSquare(_ num: Int) -> Bool {
if num < 2 { return true }
var x = num / 2
while x * x > num {
x = (x + num / x) / 2
}
return x * x == num
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 759. Employee Free Time
Сложность: hard
Нам дан список schedule of employees, который представляет собой рабочее время каждого сотрудника. У каждого сотрудника есть список непересекающихся интервалов, и эти интервалы расположены в отсортированном порядке. Верните список конечных интервалов, представляющих общее свободное время положительной длины для всех сотрудников, также в отсортированном порядке. (Хотя мы представляем интервалы в форме [x, y], объекты внутри них являются интервалами, а не списками или массивами. Например, schedule[0][0].start = 1, schedule[0][0].end = 2, а schedule[0][0][0] не определено).Также мы не будем включать в наш ответ интервалы типа [5, 5], так как они имеют нулевую длину.
Пример:
👨💻 Алгоритм:
1⃣ Объедините все интервалы всех сотрудников в один список и отсортируйте его по начальным временам.
2⃣ Объедините пересекающиеся интервалы в один.
3⃣ Найдите промежутки между объединенными интервалами, представляющие свободное время.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Нам дан список schedule of employees, который представляет собой рабочее время каждого сотрудника. У каждого сотрудника есть список непересекающихся интервалов, и эти интервалы расположены в отсортированном порядке. Верните список конечных интервалов, представляющих общее свободное время положительной длины для всех сотрудников, также в отсортированном порядке. (Хотя мы представляем интервалы в форме [x, y], объекты внутри них являются интервалами, а не списками или массивами. Например, schedule[0][0].start = 1, schedule[0][0].end = 2, а schedule[0][0][0] не определено).Также мы не будем включать в наш ответ интервалы типа [5, 5], так как они имеют нулевую длину.
Пример:
Input: schedule = [[[1,2],[5,6]],[[1,3]],[[4,10]]]
Output: [[3,4]]
class Interval {
var start: Int
var end: Int
init(_ start: Int, _ end: Int) {
self.start = start
self.end = end
}
}
func employeeFreeTime(_ schedule: [[Interval]]) -> [Interval] {
var intervals = [Interval]()
for employee in schedule {
intervals.append(contentsOf: employee)
}
intervals.sort { $0.start < $1.start }
var merged = [Interval]()
for interval in intervals {
if merged.isEmpty || merged.last!.end < interval.start {
merged.append(interval)
} else {
merged.last!.end = max(merged.last!.end, interval.end)
}
}
var freeTime = [Interval]()
for i in 1..<merged.count {
if merged[i].start > merged[i-1].end {
freeTime.append(Interval(merged[i-1].end, merged[i].start))
}
}
return freeTime
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: №43. Multiply Strings
Сложность: medium
При наличии двух неотрицательных целых чисел
Примечание: Нельзя использовать встроенные библиотеки
Пример:
👨💻 Алгоритм:
1⃣ Преобразовать строки в массивы цифр в перевернутом порядке.
2⃣ Использовать алгоритм умножения в столбик, накапливая суммы по индексам.
3⃣ Преобразовать результат обратно в строку, удаляя ведущие нули.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
При наличии двух неотрицательных целых чисел
num1 и num2, представленных в виде строк, вернуть произведение num1 и num2, также представленное в виде строки. Примечание: Нельзя использовать встроенные библиотеки
BigInteger или напрямую преобразовывать входные данные в integer. Пример:
Input: num1 = "123", num2 = "456"
Output: "56088"
class Solution {
func multiply(_ num1: String, _ num2: String) -> String {
guard num1 != "0", num2 != "0" else { return "0" }
let n1 = num1.map { Int(String($0))! }.reversed()
let n2 = num2.map { Int(String($0))! }.reversed()
var res = Array(repeating: 0, count: num1.count + num2.count)
for i in 0..<n1.count {
for j in 0..<n2.count {
res[i + j] += n1[i] * n2[j]
res[i + j + 1] += res[i + j] / 10
res[i + j] %= 10
}
}
while res.count > 1, res.last == 0 {
res.removeLast()
}
return res.reversed().map(String.init).joined()
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 129. Sum Root to Leaf Numbers
Сложность: Medium
Вам дан корень бинарного дерева, содержащего только цифры от 0 до 9.
Каждый путь от корня до листа в дереве представляет собой число.
Например, путь от корня до листа 1 -> 2 -> 3 представляет число 123.
Верните общую сумму всех чисел от корня до листа. Тестовые случаи созданы таким образом, что ответ поместится в 32-битное целое число.
Листовой узел — это узел без детей.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация:
Создайте переменные для хранения суммы чисел (rootToLeaf) и текущего числа (currNumber), а также стек для обхода дерева, начиная с корневого узла.
2⃣ Обход дерева:
Используйте стек для глубинного обхода дерева (DFS), обновляя currNumber путём умножения на 10 и добавления значения узла. Для каждого листа добавляйте currNumber к rootToLeaf.
3⃣ Возвращение результата:
По завершении обхода всех узлов возвращайте rootToLeaf, содержащую сумму всех чисел от корня до листьев дерева.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: Medium
Вам дан корень бинарного дерева, содержащего только цифры от 0 до 9.
Каждый путь от корня до листа в дереве представляет собой число.
Например, путь от корня до листа 1 -> 2 -> 3 представляет число 123.
Верните общую сумму всех чисел от корня до листа. Тестовые случаи созданы таким образом, что ответ поместится в 32-битное целое число.
Листовой узел — это узел без детей.
Пример:
Input: root = [1,2,3]
Output: 25
Explanation:
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Therefore, sum = 12 + 13 = 25.
Создайте переменные для хранения суммы чисел (rootToLeaf) и текущего числа (currNumber), а также стек для обхода дерева, начиная с корневого узла.
Используйте стек для глубинного обхода дерева (DFS), обновляя currNumber путём умножения на 10 и добавления значения узла. Для каждого листа добавляйте currNumber к rootToLeaf.
По завершении обхода всех узлов возвращайте rootToLeaf, содержащую сумму всех чисел от корня до листьев дерева.
class Solution {
func sumNumbers(_ root: TreeNode?) -> Int {
var rootToLeaf = 0, currNumber = 0
var stack: [(TreeNode?, Int)] = []
stack.append((root, 0))
while !stack.isEmpty {
let p = stack.removeLast()
let node = p.0
currNumber = p.1
if let root = node {
currNumber = currNumber * 10 + root.val
if root.left == nil && root.right == nil {
rootToLeaf += currNumber
} else {
if let right = root.right {
stack.append((right, currNumber))
}
if let left = root.left {
stack.append((left, currNumber))
}
}
}
}
return rootToLeaf
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 443. String Compression
Сложность: medium
Дан массив символов chars, сжать его, используя следующий алгоритм:
Начните с пустой строки s. Для каждой группы последовательных повторяющихся символов в chars:
Если длина группы равна 1, добавьте символ к строке s.
В противном случае добавьте символ, а за ним длину группы.
Сжатая строка s не должна возвращаться отдельно, а вместо этого должна быть сохранена в входном массиве символов chars. Обратите внимание, что длины групп, которые равны 10 или более, будут разделены на несколько символов в chars.
После того как вы закончите модификацию входного массива, верните новую длину массива.
Вы должны написать алгоритм, который использует только постоянное дополнительное пространство.
Пример:
👨💻 Алгоритм:
1⃣ Объявите переменные i – первый индекс текущей группы, и res – длина ответа (сжатой строки). Инициализируйте i = 0, res = 0.
2⃣ Пока i меньше длины chars: Найдите длину текущей группы последовательных повторяющихся символов groupLength. Добавьте chars[i] к ответу (chars[res++] = chars[i]). Если groupLength > 1, добавьте строковое представление groupLength к ответу и увеличьте res соответственно. Увеличьте i на groupLength и перейдите к следующей группе.
3⃣ Верните res.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив символов chars, сжать его, используя следующий алгоритм:
Начните с пустой строки s. Для каждой группы последовательных повторяющихся символов в chars:
Если длина группы равна 1, добавьте символ к строке s.
В противном случае добавьте символ, а за ним длину группы.
Сжатая строка s не должна возвращаться отдельно, а вместо этого должна быть сохранена в входном массиве символов chars. Обратите внимание, что длины групп, которые равны 10 или более, будут разделены на несколько символов в chars.
После того как вы закончите модификацию входного массива, верните новую длину массива.
Вы должны написать алгоритм, который использует только постоянное дополнительное пространство.
Пример:
Input: chars = ["a","a","b","b","c","c","c"]
Output: Return 6, and the first 6 characters of the input array should be: ["a","2","b","2","c","3"]
Explanation: The groups are "aa", "bb", and "ccc". This compresses to "a2b2c3".
class Solution {
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
Задача: 269. Alien Dictionary
Сложность: hard
Есть новый инопланетный язык, который использует английский алфавит. Однако порядок букв в нем неизвестен.
Вам дан список строк words из словаря инопланетного языка. Утверждается, что строки в words отсортированы лексикографически по правилам этого нового языка.
Если это утверждение неверно и данное расположение строк в words не может соответствовать никакому порядку букв, верните "".
В противном случае верните строку из уникальных букв нового инопланетного языка, отсортированных в лексикографическом порядке по правилам нового языка. Если существует несколько решений, верните любое из них.
Пример:
👨💻 Алгоритм:
1⃣ Извлечение отношений порядка и создание списков смежности:
Извлечь отношения порядка между буквами из слов.
Вставить их в список смежности, обрабатывая случаи, когда одно слово является префиксом другого.
2⃣ Подсчет числа входящих ребер:
Подсчитать количество входящих ребер (in-degree) для каждой буквы.
Построить исходящий список смежности и одновременно считать входящие ребра для каждой буквы.
3⃣ Обход в ширину (BFS):
Инициализировать очередь буквами с нулевым in-degree.
Выполнять BFS, добавляя буквы в результат, когда их in-degree становится нулевым.
Продолжать до тех пор, пока очередь не станет пустой.
Проверить наличие циклов и вернуть результат.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Есть новый инопланетный язык, который использует английский алфавит. Однако порядок букв в нем неизвестен.
Вам дан список строк words из словаря инопланетного языка. Утверждается, что строки в words отсортированы лексикографически по правилам этого нового языка.
Если это утверждение неверно и данное расположение строк в words не может соответствовать никакому порядку букв, верните "".
В противном случае верните строку из уникальных букв нового инопланетного языка, отсортированных в лексикографическом порядке по правилам нового языка. Если существует несколько решений, верните любое из них.
Пример:
Input: words = ["wrt","wrf","er","ett","rftt"]
Output: "wertf"
Извлечь отношения порядка между буквами из слов.
Вставить их в список смежности, обрабатывая случаи, когда одно слово является префиксом другого.
Подсчитать количество входящих ребер (in-degree) для каждой буквы.
Построить исходящий список смежности и одновременно считать входящие ребра для каждой буквы.
Инициализировать очередь буквами с нулевым in-degree.
Выполнять BFS, добавляя буквы в результат, когда их in-degree становится нулевым.
Продолжать до тех пор, пока очередь не станет пустой.
Проверить наличие циклов и вернуть результат.
import Foundation
class Solution {
func alienOrder(_ words: [String]) -> String {
var adjList = [Character: Set<Character>]()
var inDegree = [Character: Int]()
for word in words {
for char in word {
inDegree[char] = 0
}
}
for (firstWord, secondWord) in zip(words, words.dropFirst()) {
for (c, d) in zip(firstWord, secondWord) {
if c != d {
if !adjList[c, default: []].contains(d) {
adjList[c, default: []].insert(d)
inDegree[d, default: 0] += 1
}
break
}
}
if secondWord.count < firstWord.count && firstWord.hasPrefix(secondWord) {
return ""
}
}
var output = [Character]()
var queue = [Character]()
for (char, degree) in inDegree where degree == 0 {
queue.append(char)
}
while !queue.isEmpty {
let c = queue.removeFirst()
output.append(c)
for d in adjList[c] ?? [] {
inDegree[d]! -= 1
if inDegree[d] == 0 {
queue.append(d)
}
}
}
if output.count < inDegree.count {
return ""
}
return String(output)
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 119. Pascal's Triangle ll
Сложность: easy
Для данного целого числа rowIndex верните rowIndex-ю строку (с индексацией с нуля) треугольника Паскаля.
Пример:
👨💻 Алгоритм:
1⃣ Давайте представим, что у нас есть функция getNum(rowIndex, colIndex), которая дает нам число с индексом colIndex в строке с индексом rowIndex. Мы могли бы просто построить k-ю строку, повторно вызывая getNum(...) для столбцов от 0 до k.
2⃣ Мы можем сформулировать нашу интуицию в следующую рекурсию:
getNum(rowIndex, colIndex) = getNum(rowIndex - 1, colIndex - 1) + getNum(rowIndex - 1, colIndex)
3⃣ Рекурсия заканчивается в некоторых известных базовых случаях:
Первая строка - это просто одинокая 1, то есть getNum(0, ...) = 1
Первое и последнее число каждой строки равно 1, то есть getNum(k, 0) = getNum(k, k) = 1
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Для данного целого числа rowIndex верните rowIndex-ю строку (с индексацией с нуля) треугольника Паскаля.
Пример:
Input: rowIndex = 3
Output: [1,3,3,1]
getNum(rowIndex, colIndex) = getNum(rowIndex - 1, colIndex - 1) + getNum(rowIndex - 1, colIndex)
Первая строка - это просто одинокая 1, то есть getNum(0, ...) = 1
Первое и последнее число каждой строки равно 1, то есть getNum(k, 0) = getNum(k, k) = 1
class Solution {
func getNum(_ row: Int, _ col: Int) -> Int {
if row == 0 col==0 row == col {
return 1
}
return getNum(row - 1, col - 1) + getNum(row - 1, col)
}
func getRow(_ rowIndex: Int) -> [Int] {
var ans = [Int]()
for i in 0...rowIndex {
ans.append(getNum(rowIndex, i))
}
return ans
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1434. Number of Ways to Wear Different Hats to Each Other
Сложность: hard
Дано n человек и 40 видов шляп, пронумерованных от 1 до 40.
Дан двумерный целочисленный массив hats, где hats[i] — список всех шляп, предпочитаемых i-м человеком.
Вернуть количество способов, которыми n человек могут носить различные шляпы друг у друга.
Поскольку ответ может быть слишком большим, вернуть его по модулю 10^9 + 7.
Пример:
👨💻 Алгоритм:
1⃣ Инициализировать переменные: n - количество людей, done = 2^n - 1, MOD = 10^9 + 7, memo - двумерный массив размером 41 * done, заполненный -1, и hatsToPeople - отображение шляп на людей.
2⃣ Заполнить hatsToPeople, сопоставив каждую шляпу людям, которые её предпочитают. Реализовать функцию dp(hat, mask), которая использует мемоизацию для вычисления количества способов распределения шляп.
3⃣ Вернуть результат вызова dp(1, 0), который выполняет основное вычисление количества способов распределения шляп.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: hard
Дано n человек и 40 видов шляп, пронумерованных от 1 до 40.
Дан двумерный целочисленный массив hats, где hats[i] — список всех шляп, предпочитаемых i-м человеком.
Вернуть количество способов, которыми n человек могут носить различные шляпы друг у друга.
Поскольку ответ может быть слишком большим, вернуть его по модулю 10^9 + 7.
Пример:
Input: hats = [[3,4],[4,5],[5]]
Output: 1
Explanation: There is only one way to choose hats given the conditions.
First person choose hat 3, Second person choose hat 4 and last one hat 5.
class Solution {
var memo: [[Int]] = []
var done: Int = 0
var n: Int = 0
let MOD = 1000000007
var hatsToPeople: [Int: [Int]] = [:]
func numberWays(_ hats: [[Int]]) -> Int {
n = hats.count
for (i, hatList) in hats.enumerated() {
for hat in hatList {
hatsToPeople[hat, default: []].append(i)
}
}
done = (1 << n) - 1
memo = Array(repeating: Array(repeating: -1, count: done), count: 41)
return dp(1, 0)
}
private func dp(_ hat: Int, _ mask: Int) -> Int {
if mask == done { return 1 }
if hat > 40 { return 0 }
if memo[hat][mask] != -1 { return memo[hat][mask] }
var ans = dp(hat + 1, mask)
if let people = hatsToPeople[hat] {
for person in people {
if (mask & (1 << person)) == 0 {
ans = (ans + dp(hat + 1, mask | (1 << person))) % MOD
}
}
}
memo[hat][mask] = ans
return ans
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 637. Average of Levels in Binary Tree
Сложность: easy
Учитывая корень бинарного дерева, верните среднее значение узлов на каждом уровне в виде массива. Принимаются ответы в пределах 10-5 от фактического ответа.
Пример:
👨💻 Алгоритм:
1⃣ Обход дерева: Используйте обход в ширину (BFS) для обхода каждого уровня дерева.
2⃣ Подсчет среднего значения: Для каждого уровня дерева подсчитайте сумму значений узлов и количество узлов, чтобы вычислить среднее значение.
3⃣ Сохранение результата: Сохраните среднее значение каждого уровня в массив и верните его.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Учитывая корень бинарного дерева, верните среднее значение узлов на каждом уровне в виде массива. Принимаются ответы в пределах 10-5 от фактического ответа.
Пример:
Input: root = [3,9,20,null,null,15,7]
Output: [3.00000,14.50000,11.00000]
public class TreeNode {
public var val: Int
public var left: TreeNode?
public var right: TreeNode?
public init() { self.val = 0; self.left = nil; self.right = nil; }
public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; }
public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {
self.val = val
self.left = left
self.right = right
}
}
class Solution {
func averageOfLevels(_ root: TreeNode?) -> [Double] {
guard let root = root else { return [] }
var result = [Double]()
var queue: [TreeNode] = [root]
while !queue.isEmpty {
var levelSum = 0
let levelCount = queue.count
for _ in 0..<levelCount {
let node = queue.removeFirst()
levelSum += node.val
if let left = node.left { queue.append(left) }
if let right = node.right { queue.append(right) }
}
result.append(Double(levelSum) / Double(levelCount))
}
return result
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 540. Single Element in a Sorted Array
Сложность: medium
Дан отсортированный массив, состоящий только из целых чисел, где каждый элемент встречается ровно дважды, кроме одного элемента, который встречается ровно один раз.
Верните единственный элемент, который встречается только один раз.
Ваше решение должно работать за время O(log n) и использовать O(1) памяти.
Пример:
👨💻 Алгоритм:
1⃣ Начиная с первого элемента, итерируемся через каждый второй элемент, проверяя, является ли следующий элемент таким же, как текущий. Если нет, то текущий элемент — это искомый элемент.
2⃣ Если доходим до последнего элемента, то он является искомым элементом. Обрабатываем этот случай после завершения цикла, чтобы избежать выхода за пределы массива.
3⃣ Возвращаем найденный элемент.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан отсортированный массив, состоящий только из целых чисел, где каждый элемент встречается ровно дважды, кроме одного элемента, который встречается ровно один раз.
Верните единственный элемент, который встречается только один раз.
Ваше решение должно работать за время O(log n) и использовать O(1) памяти.
Пример:
Input: nums = [1,1,2,3,3,4,4,8,8]
Output: 2
class Solution {
func singleNonDuplicate(_ nums: [Int]) -> Int {
for i in stride(from: 0, to: nums.count - 1, by: 2) {
if nums[i] != nums[i + 1] {
return nums[i]
}
}
return nums.last!
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 999. Available Captures for Rook
Сложность: easy
Вам дана матрица 8 x 8, изображающая шахматную доску. На ней есть ровно одна белая ладья, представленная символом "R", некоторое количество белых слонов "B" и некоторое количество черных пешек "p". Пустые клетки обозначаются символом '.'. Ладья может перемещаться на любое количество клеток по горизонтали или вертикали (вверх, вниз, влево, вправо), пока не достигнет другой фигуры или края доски. Ладья атакует пешку, если она может переместиться на ее клетку за один ход. Примечание: Ладья не может перемещаться через другие фигуры, такие как слоны или пешки. Это означает, что ладья не может атаковать пешку, если путь ей преграждает другая фигура. Верните количество пешек, которые атакует белая ладья.
Пример:
👨💻 Алгоритм:
1⃣ Поиск ладьи:
Найдите координаты белой ладьи "R" на шахматной доске.
2⃣ Проверка направлений атаки:
Проверьте все четыре направления (влево, вправо, вверх, вниз) от позиции ладьи.
Перемещайтесь по каждому направлению до тех пор, пока не встретите другую фигуру или край доски.
3⃣ Подсчет атакованных пешек:
Если встреченная фигура - черная пешка "p", увеличьте счетчик атакованных пешек.
Если встреченная фигура - белый слон "B" или край доски, остановитесь в этом направлении.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Вам дана матрица 8 x 8, изображающая шахматную доску. На ней есть ровно одна белая ладья, представленная символом "R", некоторое количество белых слонов "B" и некоторое количество черных пешек "p". Пустые клетки обозначаются символом '.'. Ладья может перемещаться на любое количество клеток по горизонтали или вертикали (вверх, вниз, влево, вправо), пока не достигнет другой фигуры или края доски. Ладья атакует пешку, если она может переместиться на ее клетку за один ход. Примечание: Ладья не может перемещаться через другие фигуры, такие как слоны или пешки. Это означает, что ладья не может атаковать пешку, если путь ей преграждает другая фигура. Верните количество пешек, которые атакует белая ладья.
Пример:
Input: board = [[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","R",".",".",".","p"],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]
Output: 3
Найдите координаты белой ладьи "R" на шахматной доске.
Проверьте все четыре направления (влево, вправо, вверх, вниз) от позиции ладьи.
Перемещайтесь по каждому направлению до тех пор, пока не встретите другую фигуру или край доски.
Если встреченная фигура - черная пешка "p", увеличьте счетчик атакованных пешек.
Если встреченная фигура - белый слон "B" или край доски, остановитесь в этом направлении.
class Solution {
func numRookCaptures(_ board: [[Character]]) -> Int {
func countPawns(_ x: Int, _ y: Int, _ dx: Int, _ dy: Int) -> Int {
var x = x, y = y
while x >= 0 && x < 8 && y >= 0 && y < 8 {
if board[x][y] == "B" { break }
if board[x][y] == "p" { return 1 }
x += dx
y += dy
}
return 0
}
for i in 0..<8 {
for j in 0..<8 {
if board[i][j] == "R" {
return countPawns(i, j, -1, 0) + countPawns(i, j, 1, 0) +
countPawns(i, j, 0, -1) + countPawns(i, j, 0, 1)
}
}
}
return 0
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 36. Valid Sudoku
Сложность: medium
Определите, является ли доска Судоку размером 9 на 9 валидной. Необходимо проверить только заполненные ячейки согласно следующим правилам:
Каждая строка должна содержать цифры от 1 до 9 без повторений.
Каждый столбец должен содержать цифры от 1 до 9 без повторений.
Каждая из девяти подзон размером 3 на 3 в сетке должна содержать цифры от 1 до 9 без повторений.
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте список из 9 хеш-множеств, где хеш-множество с индексом r будет использоваться для хранения ранее увиденных чисел в строке r судоку. Аналогично инициализируйте списки из 9 хеш-множеств для отслеживания столбцов и блоков.
2⃣ Итерируйтесь по каждой позиции (r, c) в судоку. На каждой итерации, если на текущей позиции есть число:
Проверьте, существует ли это число в хеш-множестве для текущей строки, столбца или блока. Если да, верните false, потому что это второе появление числа в текущей строке, столбце или блоке.
3⃣ В противном случае обновите множество, отвечающее за отслеживание ранее увиденных чисел в текущей строке, столбце и блоке. Индекс текущего блока рассчитывается как (r / 3) * 3 + (c / 3), где / означает деление нацело.
Если дубликаты не были найдены после посещения каждой позиции на доске судоку, то судоку валидно, поэтому верните true.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Определите, является ли доска Судоку размером 9 на 9 валидной. Необходимо проверить только заполненные ячейки согласно следующим правилам:
Каждая строка должна содержать цифры от 1 до 9 без повторений.
Каждый столбец должен содержать цифры от 1 до 9 без повторений.
Каждая из девяти подзон размером 3 на 3 в сетке должна содержать цифры от 1 до 9 без повторений.
Пример:
Input: board =
[["5","3",".",".","7",".",".",".","."]
,["6",".",".","1","9","5",".",".","."]
,[".","9","8",".",".",".",".","6","."]
,["8",".",".",".","6",".",".",".","3"]
,["4",".",".","8",".","3",".",".","1"]
,["7",".",".",".","2",".",".",".","6"]
,[".","6",".",".",".",".","2","8","."]
,[".",".",".","4","1","9",".",".","5"]
,[".",".",".",".","8",".",".","7","9"]]
Output: true
Проверьте, существует ли это число в хеш-множестве для текущей строки, столбца или блока. Если да, верните false, потому что это второе появление числа в текущей строке, столбце или блоке.
Если дубликаты не были найдены после посещения каждой позиции на доске судоку, то судоку валидно, поэтому верните true.
func isValidSudoku(_ board: [[Character]]) -> Bool {
let N = 9
var rows = Array(repeating: [Character: Bool](), count: N)
var cols = Array(repeating: [Character: Bool](), count: N)
var boxes = Array(repeating: [Character: Bool](), count: N)
for r in 0..<N {
for c in 0..<N {
let val = board[r][c]
if val == "." {
continue
}
if rows[r][val] != nil {
return false
}
rows[r][val] = true
if cols[c][val] != nil {
return false
}
cols[c][val] = true
let idx = (r / 3) * 3 + (c / 3)
if boxes[idx][val] != nil {
return false
}
boxes[idx][val] = true
}
}
return true
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1472. Design Browser History
Сложность: medium
У вас есть браузер с одной вкладкой, где вы начинаете на домашней странице и можете посетить другой URL, вернуться назад на определённое количество шагов в истории или переместиться вперёд на определённое количество шагов в истории.
Реализуйте класс BrowserHistory:
BrowserHistory(string homepage) Инициализирует объект с домашней страницей браузера.
void visit(string url) Посещает URL с текущей страницы. Это очищает всю историю вперёд.
string back(int steps) Перемещает на steps шагов назад в истории. Если вы можете вернуться только на x шагов в истории, а steps > x, вы вернётесь только на x шагов. Возвращает текущий URL после перемещения назад в истории на не более чем steps шагов.
string forward(int steps) Перемещает на steps шагов вперёд в истории. Если вы можете переместиться только на x шагов вперёд в истории, а steps > x, вы переместитесь только на x шагов. Возвращает текущий URL после перемещения вперёд в истории на не более чем steps шагов.
Пример:
👨💻 Алгоритм:
1⃣ Инициализация:
Создайте класс BrowserHistory с двумя стеками (history и future) и строковой переменной current для хранения текущего URL. Инициализируйте current с домашней страницей.
2⃣ Посещение URL:
Метод visit(url) сохраняет текущий URL в стеке history, устанавливает url как текущий и очищает стек future.
3⃣ Навигация назад и вперед:
Метод back(steps) перемещает текущий URL в стек future и извлекает URL из стека history, пока шаги не будут исчерпаны или стек history не станет пустым.
Метод forward(steps) перемещает текущий URL в стек history и извлекает URL из стека future, пока шаги не будут исчерпаны или стек future не станет пустым.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
У вас есть браузер с одной вкладкой, где вы начинаете на домашней странице и можете посетить другой URL, вернуться назад на определённое количество шагов в истории или переместиться вперёд на определённое количество шагов в истории.
Реализуйте класс BrowserHistory:
BrowserHistory(string homepage) Инициализирует объект с домашней страницей браузера.
void visit(string url) Посещает URL с текущей страницы. Это очищает всю историю вперёд.
string back(int steps) Перемещает на steps шагов назад в истории. Если вы можете вернуться только на x шагов в истории, а steps > x, вы вернётесь только на x шагов. Возвращает текущий URL после перемещения назад в истории на не более чем steps шагов.
string forward(int steps) Перемещает на steps шагов вперёд в истории. Если вы можете переместиться только на x шагов вперёд в истории, а steps > x, вы переместитесь только на x шагов. Возвращает текущий URL после перемещения вперёд в истории на не более чем steps шагов.
Пример:
Input:
["BrowserHistory","visit","visit","visit","back","back","forward","visit","forward","back","back"]
[["leetcode.com"],["google.com"],["facebook.com"],["youtube.com"],[1],[1],[1],["linkedin.com"],[2],[2],[7]]
Output:
[null,null,null,null,"facebook.com","google.com","facebook.com",null,"linkedin.com","google.com","leetcode.com"]
Explanation:
BrowserHistory browserHistory = new BrowserHistory("leetcode.com");
browserHistory.visit("google.com"); // You are in "leetcode.com". Visit "google.com"
browserHistory.visit("facebook.com"); // You are in "google.com". Visit "facebook.com"
browserHistory.visit("youtube.com"); // You are in "facebook.com". Visit "youtube.com"
browserHistory.back(1); // You are in "youtube.com", move back to "facebook.com" return "facebook.com"
browserHistory.back(1); // You are in "facebook.com", move back to "google.com" return "google.com"
browserHistory.forward(1); // You are in "google.com", move forward to "facebook.com" return "facebook.com"
browserHistory.visit("linkedin.com"); // You are in "facebook.com". Visit "linkedin.com"
browserHistory.forward(2); // You are in "linkedin.com", you cannot move forward any steps.
Создайте класс BrowserHistory с двумя стеками (history и future) и строковой переменной current для хранения текущего URL. Инициализируйте current с домашней страницей.
Метод visit(url) сохраняет текущий URL в стеке history, устанавливает url как текущий и очищает стек future.
Метод back(steps) перемещает текущий URL в стек future и извлекает URL из стека history, пока шаги не будут исчерпаны или стек history не станет пустым.
Метод forward(steps) перемещает текущий URL в стек history и извлекает URL из стека future, пока шаги не будут исчерпаны или стек future не станет пустым.
class BrowserHistory {
private var history: [String]
private var future: [String]
private var current: String
init(_ homepage: String) {
history = []
future = []
current = homepage
}
func visit(_ url: String) {
history.append(current)
current = url
future = []
}
func back(_ steps: Int) -> String {
var steps = steps
while steps > 0 && !history.isEmpty {
future.append(current)
current = history.removeLast()
steps -= 1
}
return current
}
func forward(_ steps: Int) -> String {
var steps = steps
while steps > 0 && !future.isEmpty {
history.append(current)
current = future.removeLast()
steps -= 1
}
return current
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1461. Check If a String Contains All Binary Codes of Size K
Сложность: medium
Дана бинарная строка s и целое число k, верните true, если каждый бинарный код длины k является подстрокой s. В противном случае верните false.
Пример:
👨💻 Алгоритм:
1⃣ Определите количество возможных двоичных кодов длины k.
2⃣ Создайте массив для отслеживания, какие коды были найдены. Итерируйте по строке s, вычисляя хэш для текущего окна длины k и обновляя массив отслеживания.
3⃣ Возвращайте true, если все возможные коды найдены, иначе false.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дана бинарная строка s и целое число k, верните true, если каждый бинарный код длины k является подстрокой s. В противном случае верните false.
Пример:
Input: s = "00110110", k = 2
Output: true
Explanation: The binary codes of length 2 are "00", "01", "10" and "11". They can be all found as substrings at indices 0, 1, 3 and 2 respectively.
class Solution {
func hasAllCodes(_ s: String, _ k: Int) -> Bool {
let need = 1 << k
var got = [Bool](repeating: false, count: need)
let allOne = need - 1
var hashVal = 0
let chars = Array(s)
for i in 0..<chars.count {
hashVal = ((hashVal << 1) & allOne) | (chars[i] == "1" ? 1 : 0)
if i >= k - 1 && !got[hashVal] {
got[hashVal] = true
if got.allSatisfy({ $0 }) {
return true
}
}
}
return false
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 247. Strobogrammatic Number II
Сложность: medium
Дано целое число n, верните все стробограмматические числа длины n. Ответ можно возвращать в любом порядке.
Стробограмматическое число — это число, которое выглядит одинаково при повороте на 180 градусов (если посмотреть вверх ногами).
Пример:
👨💻 Алгоритм:
1⃣ Инициализируйте структуру данных reversiblePairs, которая содержит все пары обратимых цифр. Вызовите и верните результат рекурсивной функции generateStroboNumbers(n, finalLength), где первый аргумент указывает, что текущий вызов создаст все стробограмматические числа длиной n, а второй аргумент указывает длину конечных стробограмматических чисел, которые мы будем генерировать, и будет использоваться для проверки возможности добавления '0' в начало и конец числа.
2⃣ Создайте функцию generateStroboNumbers(n, finalLength), которая вернет все стробограмматические числа длиной n:
Проверьте базовые случаи: если n == 0, верните массив с пустой строкой [""]; если n == 1, верните ["0", "1", "8"].
Вызовите generateStroboNumbers(n - 2, finalLength), чтобы получить все стробограмматические числа длиной (n-2), и сохраните их в subAns.
Инициализируйте пустой массив currStroboNums для хранения стробограмматических чисел длиной n.
3⃣ Для каждого числа в subAns добавьте все reversiblePairs в начало и конец, за исключением случая, когда текущая пара '00' и n == finalLength (потому что нельзя добавить '0' в начало числа), и добавьте это новое число в currStroboNums. В конце функции верните все стробограмматические числа, т.е. currStroboNums.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дано целое число n, верните все стробограмматические числа длины n. Ответ можно возвращать в любом порядке.
Стробограмматическое число — это число, которое выглядит одинаково при повороте на 180 градусов (если посмотреть вверх ногами).
Пример:
Input: n = 2
Output: ["11","69","88","96"]
Проверьте базовые случаи: если n == 0, верните массив с пустой строкой [""]; если n == 1, верните ["0", "1", "8"].
Вызовите generateStroboNumbers(n - 2, finalLength), чтобы получить все стробограмматические числа длиной (n-2), и сохраните их в subAns.
Инициализируйте пустой массив currStroboNums для хранения стробограмматических чисел длиной n.
class Solution {
let reversiblePairs: [[Character]] = [
["0", "0"], ["1", "1"],
["6", "9"], ["8", "8"], ["9", "6"]
]
func generateStroboNumbers(_ n: Int, _ finalLength: Int) -> [String] {
if n == 0 {
return [""]
}
if n == 1 {
return ["0", "1", "8"]
}
let prevStroboNums = generateStroboNumbers(n - 2, finalLength)
var currStroboNums = [String]()
for prevStroboNum in prevStroboNums {
for pair in reversiblePairs {
if pair[0] != "0" || n != finalLength {
currStroboNums.append(String(pair[0]) + prevStroboNum + String(pair[1]))
}
}
}
return currStroboNums
}
func findStrobogrammatic(_ n: Int) -> [String] {
return generateStroboNumbers(n, n)
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1099. Two Sum Less Than K
Сложность: easy
Дан массив целых чисел nums и целое число k. Верните максимальную сумму, такую что существуют i < j, при которых nums[i] + nums[j] = sum и sum < k. Если не существует таких i и j, удовлетворяющих этому условию, верните -1.
Пример:
👨💻 Алгоритм:
1⃣ Отсортируйте массив.
2⃣ Установите указатели: левый на начало массива, правый на конец.
3⃣ Пока левый указатель меньше правого:
Если сумма элементов по указателям меньше k, обновите максимальную сумму и сдвиньте левый указатель вправо.
Иначе сдвиньте правый указатель влево.
Верните максимальную сумму.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан массив целых чисел nums и целое число k. Верните максимальную сумму, такую что существуют i < j, при которых nums[i] + nums[j] = sum и sum < k. Если не существует таких i и j, удовлетворяющих этому условию, верните -1.
Пример:
Input: nums = [34,23,1,24,75,33,54,8], k = 60
Output: 58
Explanation: We can use 34 and 24 to sum 58 which is less than 60.
Если сумма элементов по указателям меньше k, обновите максимальную сумму и сдвиньте левый указатель вправо.
Иначе сдвиньте правый указатель влево.
Верните максимальную сумму.
class Solution {
func twoSumLessThanK(_ nums: [Int], _ k: Int) -> Int {
var answer = -1
var count = [Int](repeating: 0, count: 1001)
for num in nums {
count[num] += 1
}
var lo = 1
var hi = 1000
while lo <= hi {
if lo + hi >= k || count[hi] == 0 {
hi -= 1
} else {
if count[lo] > (lo < hi ? 0 : 1) {
answer = max(answer, lo + hi)
}
lo += 1
}
}
return answer
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM