Swift | LeetCode
1.49K subscribers
126 photos
1.06K links
Cайт easyoffer.ru
Реклама @easyoffer_adv
ВП @easyoffer_vp

Тесты t.iss.one/+bn3i_aLL0-A2ZGMy
Вопросы собесов t.iss.one/+wtkjBoN6OI5hNGEy
Вакансии t.iss.one/+3o9-Ytdiv_E5OGIy
Download Telegram
Задача: №16. 3Sum Closest
Сложность: medium

Учитывая целочисленный массив nums длины n и целочисленную цель, найдите три целых числа в nums, сумма которых наиболее близка к цели. Возвращает сумму трех целых чисел. Вы можете предположить, что каждый вход будет иметь ровно одно решение.

Пример:
Input: nums = [-1,2,1,-4], target = 1  
Output: 2


👨‍💻 Алгоритм:

1⃣ Отсортировать массив, чтобы упростить поиск комбинаций.

2⃣Использовать два указателя для поиска ближайшей суммы к цели.

3⃣Обновлять минимальную разницу и результат при нахождении более близкой суммы.

😎 Решение:
class Solution {
func threeSumClosest(_ nums: [Int], _ target: Int) -> Int {
let sorted = nums.sorted()
let length = sorted.count
var diff: Int = .max
var result = 0

for i in 0..<length - 2 {
var n = i + 1, q = length - 1
while n < q {
let sum = sorted[i] + sorted[n] + sorted[q]
sum > target ? (q -= 1) : (n += 1)
let value = abs(sum - target)
if value < diff {
diff = value
result = sum
}
}
}
return result
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 995. Minimum Number of K Consecutive Bit Flips
Сложность: hard

Дан бинарный массив nums и целое число k.

Операция переворота k-бит заключается в выборе подмассива длиной k из nums и одновременном изменении каждого 0 в подмассиве на 1 и каждого 1 в подмассиве на 0.

Верните минимальное количество k-битных переворотов, необходимых для того, чтобы в массиве не осталось 0. Если это невозможно, верните -1.

Подмассив - это непрерывная часть массива.

Пример:
Input: nums = [0,1,0], k = 1
Output: 2
Explanation: Flip nums[0], then flip nums[2].


👨‍💻 Алгоритм:

1⃣Инициализация переменных:
Создайте массив flip, чтобы отслеживать, сколько раз был перевернут каждый элемент.
Инициализируйте flips для отслеживания количества текущих переворотов.

2⃣Перебор элементов массива:
Для каждого элемента определите, необходимо ли его переворачивать, учитывая текущее количество переворотов и значение в массиве.
Если нужно перевернуть, увеличьте счетчик переворотов и обновите массив flip.

3⃣Проверка возможности выполнения задачи:
Если количество переворотов больше длины массива, верните -1.

😎 Решение:
class Solution {
func minKBitFlips(_ nums: [Int], _ k: Int) -> Int {
var nums = nums
var flips = 0
var flip = 0
var flipQueue = [Int](repeating: 0, count: nums.count)

for i in 0..<nums.count {
if i >= k {
flip ^= flipQueue[i - k]
}
if nums[i] == flip {
if i + k > nums.count {
return -1
}
flips += 1
flip ^= 1
flipQueue[i] = 1
}
}
return flips
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
Осталось 3 дня!

Финальный отсчёт пошёл — осталось всего 3 дня до окончания краудфандинга easyoffer 2.0

Сейчас можно получить максимум пользы за минимальные деньги. После окончания кампании цены вырастут и вознаграждения станут недоступны.

👉 Поддержи easyoffer 2.0 и получи:

🚀 PRO подписка к easyoffer 2.0 на 1 год по цене месячной подписки. Активировать подписку можно в любой момент, например, когда начнешь искать работу. Приглашение на закрытое бета-тестирование

Поддержи проект сейчас, чтобы не забыть!

📌 Если не получается оплатить через карту РФ — напишите мне @kivaiko, и мы найдём удобный способ
Задача: 151. Reverse Words in a String
Сложность: Medium

Дана входная строка s, переверните порядок слов.

Слово определяется как последовательность символов, не являющихся пробелами. Слова в строке s разделены как минимум одним пробелом.

Верните строку, в которой слова расположены в обратном порядке, соединённые одним пробелом.

Обратите внимание, что строка s может содержать пробелы в начале или в конце, или множественные пробелы между двумя словами. Возвращаемая строка должна содержать только один пробел, разделяющий слова. Не включайте лишние пробелы.

Пример:
Input: s = "the sky is blue"
Output: "blue is sky the"


👨‍💻 Алгоритм:

1⃣Удаление лишних пробелов:
Удалите начальные и конечные пробелы из строки s. Это делается для того, чтобы убрать пробелы в начале и в конце строки, которые могут исказить конечный результат. В коде это реализовано с помощью методов erase и find_first_not_of/find_last_not_of, которые удаляют пробелы до первого и после последнего непробельного символа.

2⃣Разделение строки на слова:
Преобразуйте строку s в поток и используйте istringstream для чтения слов, разделенных пробелами. Каждое слово определяется как последовательность символов, не содержащая пробелов. Слова сохраняются в вектор words. Это делается с помощью copy, который копирует слова из потока в words с помощью istream_iterator.

3⃣Реверсирование и соединение слов:
Переверните вектор слов и соедините их обратно в одну строку, разделяя слова одним пробелом. Для реверсирования используется функция reverse, а для соединения слов — ostringstream вместе с ostream_iterator. Слова объединяются таким образом, что между ними находится только один пробел, исключая лишние пробелы между словами.

😎 Решение:
import Foundation

class Solution {
func reverseWords(_ s: String) -> String {
let trimmed = s.trimmingCharacters(in: .whitespacesAndNewlines)
let words = trimmed.split(separator: " ").reversed()
return words.joined(separator: " ")
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 918. Maximum Sum Circular Subarray
Сложность: medium

Если задан круговой целочисленный массив nums длины n, верните максимально возможную сумму непустого подмассива nums. Круговой массив означает, что конец массива соединяется с его началом. Формально, следующий элемент nums[i] равен nums[(i + 1) % n], а предыдущий элемент nums[i] равен nums[(i - 1 + n) % n]. Подмассив может включать каждый элемент фиксированного буфера nums не более одного раза. Формально, для подмассива nums[i], nums[i + 1], ..., nums[j] не существует i <= k1, k2 <= j, при этом k1 % n == k2 % n.

Пример:
Input: nums = [1,-2,3,-2]
Output: 3


👨‍💻 Алгоритм:

1⃣Найти стандартную максимальную сумму подмассива с помощью алгоритма Кадане.

2⃣Найти минимальную сумму подмассива с помощью алгоритма Кадане и вычесть ее из общей суммы массива.

3⃣Вернуть максимум между стандартной максимальной суммой подмассива и общей суммой массива минус минимальную сумму подмассива, если результат не равен 0 (чтобы учесть случай, когда все числа отрицательные).

😎 Решение:
class Solution {
func maxSubarraySumCircular(_ nums: [Int]) -> Int {
func kadane(_ arr: [Int]) -> Int {
var currentSum = arr[0], maxSum = arr[0]
for num in arr[1...] {
currentSum = max(num, currentSum + num)
maxSum = max(maxSum, currentSum)
}
return maxSum
}

let maxKadane = kadane(nums)
let totalSum = nums.reduce(0, +)
let minKadane = kadane(nums.map { -$0 })

return max(maxKadane, totalSum + minKadane == 0 ? maxKadane : totalSum + minKadane)
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
Завтра последний день!

Краудфандинг заканчивается уже завтра, и второй попытки не будет.

👉 Поддержи easyoffer 2.0 и получи:

🚀 PRO подписка к easyoffer 2.0 на 1 год по цене месячной подписки. Активировать подписку можно в любой момент, например, когда начнешь искать работу. Приглашение на закрытое бета-тестирование

📌 Если не получается оплатить через карту РФ — напишите мне @kivaiko, и мы найдём удобный способ
Задача: 1436. Destination City
Сложность: easy

Дан массив paths, где paths[i] = [cityAi, cityBi] означает, что существует прямой путь из cityAi в cityBi. Вернуть конечный город, то есть город, из которого нет пути в другой город.

Гарантируется, что граф путей образует линию без циклов, поэтому будет ровно один конечный город.

Пример:
Input: paths = [["London","New York"],["New York","Lima"],["Lima","Sao Paulo"]]
Output: "Sao Paulo"
Explanation: Starting at "London" city you will reach "Sao Paulo" city which is the destination city. Your trip consist of: "London" -> "New York" -> "Lima" -> "Sao Paulo".


👨‍💻 Алгоритм:

1⃣Для каждого города cityBi в paths проверьте, является ли он кандидатом на конечный город.

2⃣Для каждого кандидата проверьте, нет ли пути, ведущего из него (cityAi == candidate).

3⃣Верните город, который не имеет исходящих путей.

😎 Решение:
class Solution {
func destCity(_ paths: [[String]]) -> String {
for path in paths {
let candidate = path[1]
var good = true
for p in paths {
if p[0] == candidate {
good = false
break
}
}
if good {
return candidate
}
}
return ""
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
🚨 Последний шанс!

Сегодня — последний день краудфандинга.
Через несколько часов всё закроется, и больше невозможно будет поучаствовать.

Если ты хотел, но откладывал — СЕЙЧАС самое время. Займёт 2 минуты, но изменит твой подход к собеседованиям надолго.

Поддержи easyoffer 2.0 и получи:

🚀 PRO подписка к easyoffer 2.0 на 1 год по цене месячной подписки. Активировать подписку можно в любой момент, например, когда начнешь искать работу. Приглашение на закрытое бета-тестирование

PRO подписка к easyoffer 2.0:

Доступ к списку вопросов, которые задаются на собеседованиях + вероятность встречи этих вопросов + их фильтрация по грейдам, типам интервью, компаниям

Доступ к лучшим ответам на вопросы

Список самых частых задач, которые задаются на собеседовании + их фильтрация по грейдам и компаниям

Доступ к лучшим ответам на задачи

Список тестовых заданий компаний + лучшее решение

Доступ к тренажеру "Проработка вопросов", который позволит очень быстро подготовиться к самым частым вопросам

Доступ к тренажеру "Реальное собеседование", который позволит тренироваться проходить собеседование в конкретную компанию

До конца кампании — остались часы.
Поддержать: https://planeta.ru/campaigns/easyoffer

📌 Если не получается оплатить через карту РФ — напишите мне @kivaiko, и мы найдём удобный способ
Задача: 75. Sort Colors
Сложность: medium


Дан массив nums, содержащий n объектов, окрашенных в красный, белый или синий цвет. Отсортируйте их на месте так, чтобы объекты одного цвета находились рядом, а цвета располагались в порядке красный, белый и синий.

Мы будем использовать целые числа 0, 1 и 2 для обозначения красного, белого и синего цветов соответственно.

Вы должны решить эту задачу без использования функции сортировки библиотеки.

Пример:
Input: nums = [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]


👨‍💻 Алгоритм:

1⃣Инициализация крайней правой границы нулей: p0 = 0. Во время выполнения алгоритма nums[idx < p0] = 0.

2⃣Инициализация крайней левой границы двоек: p2 = n - 1. Во время выполнения алгоритма nums[idx > p2] = 2.

3⃣Инициализация индекса текущего элемента для рассмотрения: curr = 0.
Пока curr <= p2:
Если nums[curr] = 0: поменять местами элементы с индексами curr и p0, и сдвинуть оба указателя вправо.
Если nums[curr] = 2: поменять местами элементы с индексами curr и p2. Сдвинуть указатель p2 влево.
Если nums[curr] = 1: сдвинуть указатель curr вправо.

😎 Решение:
func sortColors(_ nums: inout [Int]) {
var p0 = 0, curr = 0
var p2 = nums.count - 1
while curr <= p2 {
if nums[curr] == 0 {
nums.swapAt(curr, p0)
curr += 1
p0 += 1
} else if nums[curr] == 2 {
nums.swapAt(curr, p2)
p2 -= 1
} else {
curr += 1
}
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
Такого больше не будет!

Всего пара часов и больше не будет возможности получить:

🚀 PRO подписку к easyoffer 2.0 на 1 год по цене месячной подписки. Активировать подписку можно в любой момент, например, когда начнешь искать работу. Приглашение на закрытое бета-тестирование

👉 Поддержать: https://planeta.ru/campaigns/easyoffer
Задача: 1040. Moving Stones Until Consecutive II
Сложность: medium

Есть несколько камней, расположенных в разных позициях на оси X. Вам дан целочисленный массив stones - позиции камней. Назовите камень конечным, если он имеет наименьшую или наибольшую позицию. За один ход вы берете конечный камень и перемещаете его в незанятую позицию так, чтобы он перестал быть конечным. В частности, если камни находятся, скажем, в позиции stones = [1,2,5], вы не можете переместить конечный камень в позицию 5, поскольку перемещение его в любую позицию (например, 0 или 3) сохранит этот камень в качестве конечного. Игра заканчивается, когда вы не можете сделать больше ни одного хода (т.е, камни находятся в трех последовательных позициях). Возвращает целочисленный массив answer длины 2, где: answer[0] - минимальное количество ходов, которое вы можете сделать, а answer[1] - максимальное количество ходов, которое вы можете сделать.

Пример:
Input: stones = [7,4,9]
Output: [1,2]


👨‍💻 Алгоритм:

1⃣Сортировка:
Сначала отсортируем массив камней.

2⃣Максимальное количество ходов:
Максимальное количество ходов равно (последняя позиция - первая позиция + 1) - количество камней, исключая случаи, когда уже имеются три последовательных камня.

3⃣Минимальное количество ходов:
Минимальное количество ходов можно определить следующим образом:
Если первый или последний камень уже находится на своем месте, необходимо проверить остальные камни.
Если расстояние между первым и последним камнем равно 2 (то есть, всего три камня и они расположены последовательно), то минимальное количество ходов равно 0.
В других случаях минимальное количество ходов равно либо 2 (если среди первых или последних трех камней есть два подряд и одно пропущенное), либо 1 (если можно переместить один камень в нужное место).

😎 Решение:
class Solution {
func numMovesStonesII(_ stones: [Int]) -> [Int] {
let sortedStones = stones.sorted()
let n = sortedStones.count

var maxMoves = sortedStones[n-1] - sortedStones[0] + 1 - n
maxMoves -= min(sortedStones[1] - sortedStones[0] - 1, sortedStones[n-1] - sortedStones[n-2] - 1)

var minMoves = Int.max
var j = 0

for i in 0..<n {
while j < n && sortedStones[j] - sortedStones[i] + 1 <= n {
j += 1
}
let alreadyInWindow = j - i
if alreadyInWindow == n - 1 && sortedStones[j-1] - sortedStones[i] + 1 == n - 1 {
minMoves = min(minMoves, 2)
} else {
minMoves = min(minMoves, n - alreadyInWindow)
}
}

return [minMoves, maxMoves]
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
Финальный отсчёт:
3 часа до конца краудфандинга easyoffer 2.0!


Это не просто скидка. Это шанс поддержать проект, который поможет и вам и тысячам айтишников готовиться к собеседованиям быстрее, эффективнее и увереннее.

За последние недели:
💥 Нас поддержали уже больше 1450 человек;
🔥 Вместе собрали больше 4,5 млн. рублей на запуск проекта;

Но сейчас важнее другое.

Через 3 часа всё закончится.
– Больше не будет подписки за 3 200 руб. на целый год!
– Не будет шанса первыми воспользоваться EasyOffer 2.0 на бета-тестировании

Если вы:

+ Планируете менять работу в этом или следующем году;
+ Хотите иметь под рукой 40,000+ вопросов собеседований с разборами, видео-ответами и тренажёрами;
+ Хотите зафиксировать лучшую цену на целый год… (потом будет в 12 раз дороже)

👉 Тогда просто переходите и поддержите нас сейчас:
https://planeta.ru/campaigns/easyoffer

📢 Три часа — и всё.
Не откладывайте на потом.

Спасибо всем, кто уже с нами! 💙
Forwarded from easyoffer
🚨 60 минут до финала

Через час мы закроем краудфандинг easyoffer 2.0
Это последний шанс вписаться в самые выгодные условия.

👉 https://planeta.ru/campaigns/easyoffer
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Идущий к IT
Я смотрю на эту цифру и до сих пор не верю.

Когда я запускал этот проект, мне реально было страшно. Страшно, что ничего не получится. Что я и мой проект никому не нужен. Страшно, что все увидят, как я публично обосрался.

Я ставил планку в 300т рублей. В самом позитивном сценарии 1млн. Но про 5 миллионов… даже мысли не было. Уже в первые часы стало понятно, что кампания идет не по плану. Сайт краудфандинга не выдержал нашей нагрузки и лег 😁

Особенно в последние три дня — просто какой-то разрыв! Я ощущал, как будто ловлю попутный ветер. В последний час не хватало 50к до 5 млн, и я уже думал сам их докинуть, чтобы красиво закрыть 😁

Но финальная сумма это не так важно. Самое главное это как мы её собрали. Это не инвестиции, не чьи-то деньги под условия и контроль, не кредит. Это вы поверили и поддержали меня напрямую. Вы дали мне возможность оставить за собой полный контроль над easyoffer.

Я чувствую огромную ответственность и нервничаю из-за высоких ожиданий. А вдруг что-то пойдёт не так? А вдруг на релизе кому-то что-то не понравится? Именно поэтому я рад, что могу честно выйти на новый этап и без давления от левых инвесторов.

В такие моменты вспоминаю, с чего всё начиналось. Как 2 года назад я писал свои первые посты на 500 человек о том, как учу программирование. Как записывал первое видео на YouTube про поиск работы. Как пилил первую версию easyoffer, вообще без понимания, что из этого выйдет.

И сейчас я думаю — может, эта история вдохновит кого-то из вас. Может, кто-то запустит свой айтишный проект, найдёт поддержку и соберёт бабки на развитие. Было бы круто

Спасибо за невероятную и колосальную поддержку ❤️
О такой аудитории как вы я не мог мечтать
Задача: 1249. Minimum Remove to Make Valid Parentheses
Сложность: medium

Дана строка s из '(' , ')' и строчных английских символов. Ваша задача - удалить минимальное количество скобок ( '(' или ')' в любых позициях), чтобы полученная строка со скобками была допустимой, и вернуть любую допустимую строку. Формально строка со скобками допустима тогда и только тогда, когда: она пустая, содержит только строчные символы, или может быть записана как AB (A, конкатенированная с B), где A и B - допустимые строки, или может быть записана как (A), где A - допустимая строка.

Пример:
Input: s = "lee(t(c)o)de)"
Output: "lee(t(c)o)de"


👨‍💻 Алгоритм:

1⃣Пройдите по строке s и сохраните индексы всех открывающих скобок '(' в стек. При встрече закрывающей скобки ')', удалите соответствующую открытую скобку из стека. Если в стеке нет соответствующей открывающей скобки, пометьте эту закрывающую скобку для удаления.

2⃣После первого прохода, все оставшиеся в стеке открывающие скобки пометьте для удаления.

3⃣Создайте новую строку, удалив все помеченные скобки.

😎 Решение:
class Solution {
func minRemoveToMakeValid(_ s: String) -> String {
var stack = [Int]()
var s = Array(s)
for i in 0..<s.count {
if s[i] == "(" {
stack.append(i)
} else if s[i] == ")" {
if !stack.isEmpty {
stack.removeLast()
} else {
s[i] = "*"
}
}
}
while !stack.isEmpty {
s[stack.removeLast()] = "*"
}
return String(s).replacingOccurrences(of: "*", with: "")
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1122. Relative Sort Array
Сложность: easy

Даны два массива arr1 и arr2, элементы arr2 уникальны, и все элементы arr2 также присутствуют в arr1.

Отсортируйте элементы arr1 таким образом, чтобы относительный порядок элементов в arr1 был таким же, как в arr2. Элементы, которые не встречаются в arr2, должны быть размещены в конце arr1 в порядке возрастания.

Пример:
Input: arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
Output: [2,2,2,1,4,3,3,9,6,7,19]


👨‍💻 Алгоритм:

1⃣Инициализация и подсчёт:
Инициализируйте пустой массив result и массив remaining для хранения оставшихся элементов.
Создайте хеш-таблицу countMap для хранения количества вхождений каждого элемента из arr2 в arr1.

2⃣Заполнение countMap и remaining:
Пройдитесь по элементам arr1 и если элемент присутствует в countMap, увеличьте его счетчик. Если элемент не присутствует в arr2, добавьте его в remaining.

3⃣Формирование результирующего массива:
Пройдитесь по arr2 и добавьте элементы в result в соответствии с их количеством в countMap.
Отсортируйте массив remaining и добавьте его элементы в result.
Верните result в виде массива.

😎 Решение:
class Solution {
func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] {
var countMap = [Int: Int]()
var remaining = [Int]()
var result = [Int]()

for value in arr2 {
countMap[value] = 0
}

for value in arr1 {
if let _ = countMap[value] {
countMap[value]! += 1
} else {
remaining.append(value)
}
}

remaining.sort()

for value in arr2 {
if let count = countMap[value] {
for _ in 0..<count {
result.append(value)
}
}
}

result.append(contentsOf: remaining)
return result
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 76. Minimum Window Substring
Сложность: hard

Даны две строки s и t длиной m и n соответственно. Верните наименьшую подстроку строки s так, чтобы каждый символ из строки t (включая дубликаты) входил в эту подстроку. Если такой подстроки не существует, верните пустую строку "".

Тестовые примеры будут сформированы таким образом, что ответ будет уникальным.

Пример:
Input: s = "ADOBECODEBANC", t = "ABC"
Output: "BANC"
Explanation: The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t.


👨‍💻 Алгоритм:

1⃣Мы начинаем с двух указателей, left и right, которые изначально указывают на первый элемент строки S.

2⃣Мы используем указатель right для расширения окна до тех пор, пока не получим желаемое окно, т.е. окно, которое содержит все символы из T.

3⃣Как только у нас есть окно со всеми символами, мы можем передвигать указатель left вперёд по одному. Если окно по-прежнему желаемое, мы продолжаем обновлять размер минимального окна. Если окно больше не желаемое, мы повторяем шаг 2 и далее.

😎 Решение:
func minWindow(_ s: String, _ t: String) -> String {
if s.isEmpty || t.isEmpty {
return ""
}

var dictT = [Character: Int]()
for char in t {
dictT[char, default: 0] += 1
}

let required = dictT.count
var l = 0
var r = 0
var formed = 0
var windowCounts = [Character: Int]()
var ans = (-1, 0, 0)

let sChars = Array(s)

while r < sChars.count {
let c = sChars[r]
windowCounts[c, default: 0] += 1

if let tCount = dictT[c], windowCounts[c] == tCount {
formed += 1
}

while l <= r && formed == required {
let c = sChars[l]

if ans.0 == -1 || r - l + 1 < ans.0 {
ans = (r - l + 1, l, r)
}

windowCounts[c, default: 0] -= 1
if let tCount = dictT[c], windowCounts[c] < tCount {
formed -= 1
}
l += 1
}
r += 1
}

if ans.0 == -1 {
return ""
} else {
let startIndex = s.index(s.startIndex, offsetBy: ans.1)
let endIndex = s.index(s.startIndex, offsetBy: ans.2)
return String(s[startIndex...endIndex])
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1162. As Far from Land as Possible
Сложность: medium

Дана сетка размером n x n, содержащая только значения 0 и 1, где 0 представляет воду, а 1 представляет землю. Найдите ячейку с водой, такое что её расстояние до ближайшей ячейки с землёй максимально, и верните это расстояние. Если в сетке нет ни земли, ни воды, верните -1.

Расстояние, используемое в этой задаче, - это манхэттенское расстояние: расстояние между двумя ячейками (x0, y0) и (x1, y1) равно |x0 - x1| + |y0 - y1|.

Пример:
Input: grid = [[1,0,1],[0,0,0],[1,0,1]]
Output: 2
Explanation: The cell (1, 1) is as far as possible from all the land with distance 2.


👨‍💻 Алгоритм:

1⃣Итерируйте по матрице и вставьте координаты ячеек с землёй в очередь. Инициализируйте переменную distance значением -1 для хранения текущего шага обхода в ширину (BFS). Также создайте копию матрицы visited для пометки ячеек с водой как посещённые, чтобы не вставлять их снова в очередь.

2⃣Выполните BFS: Обходите текущие элементы в очереди и для каждого элемента проверяйте координаты в четырёх направлениях, являются ли они ячейками с водой (0). Если да, вставьте их в очередь и измените их на ячейки с землёй (1) в матрице visited. После каждого пройденного уровня (внутренний цикл while завершён), увеличьте переменную distance.

3⃣Повторяйте, пока очередь не станет пустой. Верните значение distance. Если оно равно 0, это означает, что не было ячеек с водой и обход завершился после первого шага, поэтому верните -1. Если в матрице не было ячеек с землёй, цикл while вообще не начнётся, и переменная distance останется с начальным значением (-1).

😎 Решение
class Solution {
let directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]

func maxDistance(_ grid: [[Int]]) -> Int {
var visited = grid
var q = [(Int, Int)]()

for i in 0..<grid.count {
for j in 0..<grid[0].count {
if grid[i][j] == 1 {
q.append((i, j))
}
}
}

var distance = -1
while !q.isEmpty {
let qSize = q.count
for _ in 0..<qSize {
let landCell = q.removeFirst()
for dir in directions {
let x = landCell.0 + dir.0
let y = landCell.1 + dir.1

if x >= 0 && y >= 0 && x < grid.count && y < grid[0].count && visited[x][y] == 0 {
visited[x][y] = 1
q.append((x, y))
}
}
}
distance += 1
}

return distance == 0 ? -1 : distance
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 149. Max Points on a Line
Сложность: Hard

Дан массив точек, где points[i] = [xi, yi] представляет точку на плоскости XY. Верните максимальное количество точек, которые лежат на одной прямой.

Пример:
Input: points = [[1,1],[2,2],[3,3]]
Output: 3


👨‍💻 Алгоритм:

1⃣Итерация по всем точкам:
Проходим по всем точкам массива. Пусть текущая точка будет points[i]. Создаём хеш-таблицу cnt для подсчёта углов.

2⃣Расчёт углов и подсчёт:
Для каждой точки j, не равной i, рассчитываем арктангенс вектора points[j] - points[i] и добавляем это значение в хеш-таблицу.

3⃣Обновление ответа:
Пусть k будет максимальным количеством вхождений какого-либо значения угла в хеш-таблице. Обновляем ответ значением k + 1 (прибавляем 1, потому что точка points[i] также лежит на этой линии, и её нужно включить в ответ).

😎 Решение:
class Solution {
func maxPoints(_ points: [[Int]]) -> Int {
let n = points.count
if n == 1 {
return 1
}
var result = 2
for i in 0..<n {
var cnt = [Double: Int]()
for j in 0..<n {
if j != i {
let dy = Double(points[j][1] - points[i][1])
let dx = Double(points[j][0] - points[i][0])
let angle = atan2(dy, dx)
cnt[angle, default: 0] += 1
}
}
for (_, count) in cnt {
result = max(result, count + 1)
}
}
return result
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1027. Longest Arithmetic Subsequence
Сложность: medium

Если задан массив nums целых чисел, верните длину самой длинной арифметической подпоследовательности в nums. Примечание: Подпоследовательность - это массив, который может быть получен из другого массива путем удаления некоторых или ни одного элемента без изменения порядка оставшихся элементов. Последовательность seq является арифметической, если seq[i + 1] - seq[i] имеют одинаковое значение (для 0 <= i < seq.length - 1).

Пример:
Input: nums = [3,6,9,12]
Output: 4


👨‍💻 Алгоритм:

1⃣Инициализация переменных:
Создайте массив словарей dp, где dp[i][d] будет хранить длину самой длинной арифметической подпоследовательности, заканчивающейся на элементе i с разностью d.

2⃣Заполнение массива dp:
Пройдитесь по каждому элементу массива nums.
Для каждого элемента nums[j] (где j идет от 0 до i-1), вычислите разность d = nums[i] - nums[j].
Обновите dp[i][d] на основе значения dp[j][d].

3⃣Поиск максимальной длины:
Пройдите по массиву dp и найдите максимальное значение среди всех значений dp[i][d].

😎 Решение:
class Solution {
func longestArithSeqLength(_ nums: [Int]) -> Int {
if nums.isEmpty { return 0 }

var dp = Array(repeating: [Int: Int](), count: nums.count)
var max_length = 0

for i in 0..<nums.count {
for j in 0..<i {
let diff = nums[i] - nums[j]
if let length = dp[j][diff] {
dp[i][diff] = length + 1
} else {
dp[i][diff] = 2 // Start a new sequence
}
max_length = max(max_length, dp[i][diff]!)
}
}

return max_length
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM