ar
Feedback
Swift | LeetCode

Swift | LeetCode

الذهاب إلى القناة على Telegram
1 325
المشتركون
لا توجد بيانات24 ساعات
+17 أيام
-1030 أيام

جاري تحميل البيانات...

جذب المشتركين
أغسطس '26
أغسطس '26
+8
في 0 قنوات
يوليو '26
+3
في 0 قنوات
Get PRO
يونيو '26
+4
في 1 قنوات
Get PRO
مايو '26
+4
في 0 قنوات
Get PRO
أبريل '26
+6
في 0 قنوات
Get PRO
مارس '26
+4
في 0 قنوات
Get PRO
فبراير '26
+9
في 0 قنوات
Get PRO
يناير '26
+17
في 0 قنوات
Get PRO
ديسمبر '25
+12
في 0 قنوات
Get PRO
نوفمبر '25
+54
في 0 قنوات
Get PRO
أكتوبر '25
+30
في 0 قنوات
Get PRO
سبتمبر '25
+32
في 0 قنوات
Get PRO
أغسطس '25
+37
في 0 قنوات
Get PRO
يوليو '25
+34
في 1 قنوات
Get PRO
يونيو '25
+30
في 0 قنوات
Get PRO
مايو '25
+33
في 0 قنوات
Get PRO
أبريل '25
+68
في 0 قنوات
Get PRO
مارس '25
+143
في 2 قنوات
Get PRO
فبراير '25
+113
في 1 قنوات
Get PRO
يناير '25
+113
في 53 قنوات
Get PRO
ديسمبر '24
+50
في 0 قنوات
Get PRO
نوفمبر '24
+55
في 0 قنوات
Get PRO
أكتوبر '24
+143
في 12 قنوات
Get PRO
سبتمبر '24
+459
في 331 قنوات
Get PRO
أغسطس '24
+87
في 0 قنوات
Get PRO
يوليو '24
+325
في 219 قنوات
Get PRO
يونيو '24
+261
في 232 قنوات
التاريخ
نمو المشتركين
الإشارات
القنوات
26 أغسطس+1
25 أغسطس0
24 أغسطس+1
23 أغسطس+1
22 أغسطس+1
21 أغسطس0
20 أغسطس+1
19 أغسطس0
18 أغسطس+1
17 أغسطس0
16 أغسطس0
15 أغسطس0
14 أغسطس0
13 أغسطس0
12 أغسطس0
11 أغسطس0
10 أغسطس0
09 أغسطس0
08 أغسطس0
07 أغسطس0
06 أغسطس0
05 أغسطس+1
04 أغسطس0
03 أغسطس0
02 أغسطس+1
01 أغسطس0
منشورات القناة
Задача: 561. Array Partition Сложность: easy Дан массив целых чисел nums из 2n элементов. Разделите эти числа на n пар (a1, b1), (a2, b2), ..., (an, bn) так, чтобы сумма min(ai, bi) для всех i была максимальной. Верните максимальную сумму. Пример:
Input: nums = [1,4,3,2]
Output: 4
Explanation: All possible pairings (ignoring the ordering of elements) are:
1. (1, 4), (2, 3) -> min(1, 4) + min(2, 3) = 1 + 2 = 3
2. (1, 3), (2, 4) -> min(1, 3) + min(2, 4) = 1 + 2 = 3
3. (1, 2), (3, 4) -> min(1, 2) + min(3, 4) = 1 + 3 = 4
So the maximum possible sum is 4.
👨‍💻 Алгоритм: 1⃣Отсортируйте массив nums в неубывающем порядке. 2⃣Итерируйте через массив, выбирая каждый второй элемент (начиная с первого). 3⃣Суммируйте выбранные элементы и верните эту сумму. 😎 Решение:
class Solution {
    func arrayPairSum(_ nums: [Int]) -> Int {
        let sortedNums = nums.sorted()
        var sum = 0
        for i in stride(from: 0, to: sortedNums.count, by: 2) {
            sum += sortedNums[i]
        }
        return sum
    }
}
Ставь 👍 и забирай 📚 Базу знаний

2
Задача: 188. Best Time to Buy and Sell Stock IV Сложность: hard Дан массив целых чисел prices, где prices[i] - это цена данной акции в i-й день, и целое число k. Найдите максимальную прибыль, которую вы можете получить. Вы можете завершить не более чем k транзакций, т.е. вы можете купить не более k раз и продать не более k раз. Обратите внимание: Вы не можете участвовать в нескольких транзакциях одновременно (т.е., вы должны продать акцию, прежде чем снова купить). Пример: Input: k = 2, prices = [2,4,1] Output: 2 Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2. 👨‍💻 Алгоритм: 1⃣Инициализация DP массива: Инициализируйте трехмерный массив dp, где dp[i][j][l] представляет максимальную прибыль на конец i-го дня с j оставшимися транзакциями и l акциями в портфеле. Начните с dp[0][0][0] = 0 (нет прибыли без акций и транзакций) и dp[0][1][1] = -prices[0] (покупка первой акции). 2⃣Вычисление переходов: Для каждого дня и каждого возможного количества транзакций вычислите возможные действия: держать акцию, не держать акцию, купить акцию, если j > 0, или продать акцию. Обновляйте dp с использованием: dp[i][j][1] = max(dp[i−1][j][1], dp[i−1][j−1][0] - prices[i]) (максимум между удержанием акции и покупкой новой). dp[i][j][0] = max(dp[i−1][j][0], dp[i−1][j][1] + prices[i]) (максимум между неудержанием акции и продажей). 3⃣Расчет результатов: По завершении всех дней, возвращайте максимальное значение dp[n-1][j][0] для всех j от 0 до k, что представляет максимальную прибыль без удержания акций на последний день. Обработайте специальный случай, когда 𝑘×2≥𝑛, чтобы избежать лишних расчетов. 😎 Решение: class Solution { func maxProfit(_ k: Int, _ prices: [Int]) -> Int { let n = prices.count if n <= 0 || k <= 0 { return 0 } if k * 2 >= n { return prices.dropFirst().enumerated().reduce(0) { $0 + max(0, prices[$1.offset + 1] - prices[$1.offset]) } } var dp = Array(repeating: Array(repeating: [Int.min / 2, Int.min / 2], count: k + 1), count: n) dp[0][0][0] = 0 dp[0][1][1] = -prices[0] for i in 1..<n { for j in 0...k { dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]) if j > 0 { dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]) } } } return dp[n - 1].map { $0[0] }.max() ?? 0 } } Ставь 👍 и забирай 📚 Базу знаний
48
3
Пожизненный PRO доступ на easyoffer — по цене одного года! До 2 сентября вы можете купить PRO навсегда. Покупаешь один раз — пользуешься всю жизнь. – База вопросов и задач из собеседований – Примеры видео-ответов на вопросы – Записи реальных собеседований – Тренажеры "Проработка вопросов" и "Реальное собеседование" – Аналитика требований из вакансий – Автоотклики на вакансии – Агрегатор вакансий (скоро) 👉 Купить PRO со скидкой 70%: https://easyoffer.ru/pro
53
4
Задача: 556. Next Greater Element III Сложность: medium Мы можем перемешать строку s, чтобы получить строку t, используя следующий алгоритм: Дано положительное целое число n. Найдите наименьшее целое число, которое имеет точно такие же цифры, как и число n, и больше самого числа n по значению. Если такого положительного целого числа не существует, верните -1. Учтите, что возвращенное число должно помещаться в 32-битное целое число. Если существует допустимый ответ, но он не помещается в 32-битное целое число, верните -1. Пример: Input: n = 12 Output: 21 👨‍💻 Алгоритм: 1⃣Нахождение и перестановка цифр Преобразуйте число n в массив цифр. Найдите первую цифру, которая нарушает убывающий порядок (с конца массива). Назовем её индексом i. Найдите первую цифру, которая больше digits[i-1] (с конца массива). Назовем её индексом j. Поменяйте местами цифры на позициях i-1 и j. 2⃣Обратный порядок оставшихся цифр Обратный порядок части массива от индекса i до конца, чтобы получить наименьшую перестановку, которая больше исходной. 3⃣Проверка результата и преобразование обратно в число Преобразуйте массив цифр обратно в число. Если число превышает 32-битный предел, верните -1. В противном случае верните полученное число. 😎 Решение: class Solution { private func swap(_ s: String, _ i0: Int, _ i1: Int) -> String { if i0 == i1 { return s } var chars = Array(s) chars.swapAt(i0, i1) return String(chars) } private var list = [String]() private func permute(_ a: String, _ l: Int, _ r: Int) { if l == r { list.append(a) } else { var a = a for i in l...r { a = swap(a, l, i) permute(a, l + 1, r) a = swap(a, l, i) } } } func nextGreaterElement(_ n: Int) -> Int { let s = String(n) permute(s, 0, s.count - 1) list.sort() if let index = list.firstIndex(of: s), index < list.count - 1 { if let result = Int(list[index + 1]), result <= Int32.max { return result } } return -1 } } Ставь 👍 и забирай 📚 Базу знаний
54
5
Задача: 1328. Break a Palindrome Сложность: medium Дана палиндромная строка из строчных английских букв palindrome. Замените ровно один символ на любую строчную английскую букву так, чтобы результирующая строка не была палиндромом и чтобы она была лексикографически наименьшей из возможных. Верните получившуюся строку. Если нет способа заменить символ, чтобы строка перестала быть палиндромом, верните пустую строку. Строка a лексикографически меньше строки b (одинаковой длины), если в первой позиции, где они отличаются, у строки a символ строго меньше соответствующего символа в строке b. Например, "abcc" лексикографически меньше "abcd", потому что первой различающейся позицией является четвертая, и 'c' меньше, чем 'd'. Пример: Input: palindrome = "abccba" Output: "aaccba" Explanation: There are many ways to make "abccba" not a palindrome, such as "zbccba", "aaccba", and "abacba". Of all the ways, "aaccba" is the lexicographically smallest. 👨‍💻 Алгоритм: 1⃣Если длина строки равна 1, верните пустую строку, так как невозможно создать непалиндромическую строку в этом случае. 2⃣Итерируйтесь по строке слева до середины строки: если символ не равен 'a', измените его на 'a' и верните строку. 3⃣Если вы прошли всю левую часть строки и все еще не получили непалиндромическую строку, это означает, что строка состоит только из 'a'. Следовательно, измените последний символ на 'b' и верните полученную строку. 😎 Решение class Solution { func breakPalindrome(_ palindrome: String) -> String { var palindromeArray = Array(palindrome) let length = palindromeArray.count if length == 1 { return "" } for i in 0..<length / 2 { if palindromeArray[i] != "a" { palindromeArray[i] = "a" return String(palindromeArray) } } palindromeArray[length - 1] = "b" return String(palindromeArray) } } Ставь 👍 и забирай 📚 Базу знаний
58
6
Задача: 219. Contains Duplicate II Сложность: easy Дан массив целых чисел nums и целое число k. Верните true, если в массиве существуют два различных индекса i и j, такие что nums[i] == nums[j] и abs(i - j) <= k. Пример: Input: nums = [1,2,3,1,2,3], k = 2 Output: false 👨‍💻 Алгоритм: 1⃣Создайте пустое множество set. 2⃣Пройдитесь по массиву nums: Если текущий элемент уже есть в множестве, верните true. Добавьте текущий элемент в множество. Если размер множества больше k, удалите элемент, который был добавлен k шагов назад. 3⃣Если не найдены дублирующиеся элементы на расстоянии k или менее, верните false. 😎 Решение: class Solution { func containsNearbyDuplicate(_ nums: [Int], _ k: Int) -> Bool { var set = Set<Int>() for i in 0..<nums.count { if set.contains(nums[i]) { return true } set.insert(nums[i]) if set.count > k { set.remove(nums[i - k]) } } return false } } Ставь 👍 и забирай 📚 Базу знаний
75
7
Задача: 946. Validate Stack Sequences Сложность: medium Вам дан целочисленный массив nums. За один ход вы можете выбрать индекс i, где 0 <= i < nums.length, и увеличить nums[i] на 1. Верните минимальное количество ходов, чтобы каждое значение в nums было уникальным. Тестовые примеры генерируются так, чтобы ответ умещался в 32-битное целое число. Пример: Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1] Output: true 👨‍💻 Алгоритм: 1⃣Инициализировать пустой стек. Использовать указатель j для отслеживания текущей позиции в массиве popped. 2⃣Пройти по каждому элементу в массиве pushed: Добавить элемент в стек. Проверить верхний элемент стека: Если он совпадает с текущим элементом в popped, удалить элемент из стека и увеличить указатель j. 3⃣В конце вернуть true, если указатель j достиг конца массива popped, иначе вернуть false. 😎 Решение: class Solution { func validateStackSequences(_ pushed: [Int], _ popped: [Int]) -> Bool { var stack = [Int]() var j = 0 for x in pushed { stack.append(x) while !stack.isEmpty && j < popped.count && stack.last == popped[j] { stack.removeLast() j += 1 } } return j == popped.count } } Ставь 👍 и забирай 📚 Базу знаний
77
8
Задача: 1041. Robot Bounded In Circle Сложность: medium На бесконечной плоскости робот изначально стоит в точке (0, 0) и обращен лицом на север. Обратите внимание, что: северное направление - это положительное направление оси y. южное направление - это отрицательное направление оси y. восточное направление - это положительное направление оси x. западное направление - это отрицательное направление оси x. робот может получить одну из трех команд: "G": идти прямо 1 единицу. "L": повернуть на 90 градусов влево (т.е, "R": повернуть на 90 градусов вправо (т. е. по часовой стрелке). Робот выполняет данные инструкции по порядку и повторяет их до бесконечности. Возвращается true тогда и только тогда, когда в плоскости существует окружность, такая, что робот никогда не покидает ее. Пример: Input: instructions = "GGLLGG" Output: true 👨‍💻 Алгоритм: 1⃣Понимание поведения робота: Мы анализируем, как робот движется в пределах одной серии команд. Если он вернется в начальную точку или изменит направление после выполнения всех команд, значит, он будет двигаться по замкнутой траектории, что соответствует условию задачи. 2⃣Изменение направления: Робот может двигаться на север (0), восток (1), юг (2), или запад (3). Эти направления можно моделировать с помощью векторов (dx, dy): север (0, 1), восток (1, 0), юг (0, -1), запад (-1, 0). 3⃣Обработка команд: Пройдите по всем командам и обновите позицию робота и направление, в котором он движется. Проверка состояния робота: После выполнения всех команд проверьте, вернулся ли робот в начальную точку (0, 0) или изменил направление. Если одно из этих условий выполнено, робот будет двигаться по замкнутой траектории. 😎 Решение: class Solution { func isRobotBounded(_ instructions: String) -> Bool { let directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] var x = 0 var y = 0 var direction = 0 for instruction in instructions { if instruction == "G" { x += directions[direction].0 y += directions[direction].1 } else if instruction == "L" { direction = (direction + 3) % 4 } else if instruction == "R" { direction = (direction + 1) % 4 } } return (x == 0 && y == 0) || direction != 0 } } Ставь 👍 и забирай 📚 Базу знаний
77
9
Задача: 1315. Sum of Nodes with Even-Valued Grandparent Сложность: medium Given the root of a binary tree, return the sum of values of nodes with an even-valued grandparent. If there are no nodes with an even-valued grandparent, return 0. A grandparent of a node is the parent of its parent if it exists. Пример: Input: root = [6,7,8,2,7,1,3,9,null,1,4,null,null,null,5] Output: 18 Explanation: The red nodes are the nodes with even-value grandparent while the blue nodes are the even-value grandparents. 👨‍💻 Алгоритм: 1⃣Создайте целочисленную переменную n и инициализируйте её размером строки s. Создайте строковую переменную sReverse и установите её значение как обратную строку s. 2⃣Создайте двумерный массив memo размером n + 1 на n + 1, где memo[i][j] будет содержать длину наибольшей общей подпоследовательности, учитывая первые i символов строки s и первые j символов строки sReverse. Инициализируйте массив значением -1. 3⃣Верните n - lcs(s, sReverse, n, n, memo), где lcs - это рекурсивный метод с четырьмя параметрами: первая строка s1, вторая строка s2, длина подстроки от начала s1, длина подстроки от начала s2 и memo. Метод возвращает длину наибольшей общей подпоследовательности в подстроках s1 и s2. В этом методе выполните следующее: Если m == 0 или n == 0, это означает, что одна из двух подстрок пуста, поэтому верните 0. Если memo[m][n] != -1, это означает, что мы уже решили эту подзадачу, поэтому верните memo[m][n]. Если последние символы подстрок совпадают, добавьте 1 и найдите длину наибольшей общей подпоследовательности, исключив последний символ обеих подстрок. Верните memo[i][j] = 1 + lcs(s1, s2, m - 1, n - 1, memo). В противном случае, если последние символы не совпадают, рекурсивно найдите наибольшую общую подпоследовательность в обеих подстроках, исключив их последние символы по одному. Верните memo[i][j] = max(lcs(s1, s2, m - 1, n, memo), lcs(s1, s2, m, n - 1, memo)). 😎 Решение class Solution { lcs(s1, s2, m, n, memo) { if (m == 0 || n == 0) { return 0; } if (memo[m][n] !== -1) { return memo[m][n]; } if (s1[m - 1] === s2[n - 1]) { memo[m][n] = 1 + this.lcs(s1, s2, m - 1, n - 1, memo); } else { memo[m][n] = Math.max(this.lcs(s1, s2, m - 1, n, memo), this.lcs(s1, s2, m, n - 1, memo)); } return memo[m][n]; } minInsertions(s) { const n = s.length; const sReverse = s.split('').reverse().join(''); const memo = Array.from({ length: n + 1 }, () => Array(n + 1).fill(-1)); return n - this.lcs(s, sReverse, n, n, memo); } } Ставь 👍 и забирай 📚 Базу знаний
71
10
Задача: 1503. Last Moment Before All Ants Fall Out of a Plank Сложность: medium У нас есть деревянная доска длиной n единиц. Некоторые муравьи ходят по доске, каждый муравей движется со скоростью 1 единица в секунду. Некоторые муравьи движутся влево, другие движутся вправо. Когда два муравья, движущиеся в разных направлениях, встречаются в какой-то точке, они меняют свои направления и продолжают двигаться дальше. Предполагается, что изменение направлений не занимает дополнительного времени. Когда муравей достигает одного из концов доски в момент времени t, он сразу же падает с доски. Дано целое число n и два целых массива left и right, обозначающие позиции муравьев, движущихся влево и вправо соответственно. Верните момент, когда последний(е) муравей(и) падает(ют) с доски. Пример: Input: n = 4, left = [4,3], right = [0,1] Output: 4 Explanation: In the image above: -The ant at index 0 is named A and going to the right. -The ant at index 1 is named B and going to the right. -The ant at index 3 is named C and going to the left. -The ant at index 4 is named D and going to the left. The last moment when an ant was on the plank is t = 4 seconds. After that, it falls immediately out of the plank. (i.e., We can say that at t = 4.0000000001, there are no ants on the plank). 👨‍💻 Алгоритм: 1⃣Инициализируйте переменную ans значением 0. 2⃣Итерация по массиву left и обновление ans значением num, если оно больше текущего значения ans. 3⃣Итерация по массиву right и обновление ans значением n - num, если оно больше текущего значения ans. Верните значение ans. 😎 Решение class Solution { func getLastMoment(_ n: Int, _ left: [Int], _ right: [Int]) -> Int { var ans = 0 for num in left { ans = max(ans, num) } for num in right { ans = max(ans, n - num) } return ans } } Ставь 👍 и забирай 📚 Базу знаний
67
11
Задача: 737. Sentence Similarity II Сложность: medium Мы можем представить предложение в виде массива слов, например, предложение "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 👨‍💻 Алгоритм: 1⃣Проверить, одинаковой ли длины предложения sentence1 и sentence2. Если нет, вернуть false. 2⃣Построить граф схожести слов с использованием словаря. 3⃣Использовать поиск в глубину (DFS) для проверки транзитивной схожести слов в предложениях. 😎 Решение: 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 } Ставь 👍 и забирай 📚 Базу знаний
72
12
Задача: 1208. Get Equal Substrings Within Budget Сложность: medium Вам даны две строки s и t одинаковой длины и целое число maxCost. Вы хотите преобразовать s в t. Изменение i-го символа строки s на i-й символ строки t стоит |s[i] - t[i]| (т.е. абсолютная разница между значениями ASCII символов). Верните максимальную длину подстроки s, которую можно изменить, чтобы она соответствовала соответствующей подстроке t с затратами, не превышающими maxCost. Если нет подстроки из s, которую можно изменить на соответствующую подстроку из t, верните 0. Пример: Input: s = "abcd", t = "bcdf", maxCost = 3 Output: 3 Explanation: "abc" of s can change to "bcd". That costs 3, so the maximum length is 3. 👨‍💻 Алгоритм: 1⃣Инициализация переменных: maxLen для хранения максимальной длины подстроки с затратами, не превышающими maxCost. start для хранения начального индекса текущей подстроки. currCost для хранения текущих затрат на преобразование подстроки s в t. 2⃣Итерация по индексам от 0 до N-1: Добавить текущие затраты на преобразование символа s[i] в t[i] к currCost. Удалять элементы с левого конца, уменьшая затраты до тех пор, пока currCost не станет меньше или равным maxCost. Обновить maxLen длиной текущей подстроки. 3⃣Возврат maxLen как результата. 😎 Решение: class Solution { func equalSubstring(_ s: String, _ t: String, _ maxCost: Int) -> Int { let sArray = Array(s) let tArray = Array(t) let N = sArray.count var maxLen = 0 var start = 0 var currCost = 0 for i in 0..<N { currCost += abs(Int(sArray[i].asciiValue!) - Int(tArray[i].asciiValue!)) while currCost > maxCost { currCost -= abs(Int(sArray[start].asciiValue!) - Int(tArray[start].asciiValue!)) start += 1 } maxLen = max(maxLen, i - start + 1) } return maxLen } } Ставь 👍 и забирай 📚 Базу знаний
63
13
Задача: 987. Vertical Order Traversal of a Binary Tree Сложность: medium Вам даны два списка закрытых интервалов, firstList и secondList, где firstList[i] = [starti, endi] и secondList[j] = [startj, endj]. Каждый список интервалов является попарно непересекающимся и отсортированным. Верните пересечение этих двух списков интервалов. Закрытый интервал [a, b] (где a <= b) обозначает множество действительных чисел x с a <= x <= b. Пересечение двух закрытых интервалов - это множество действительных чисел, которые либо пусты, либо представлены как закрытый интервал. Например, пересечение [1, 3] и [2, 4] равно [2, 3]. Пример: Input: root = [3,9,20,null,null,15,7] Output: [[9],[3,15],[20],[7]] 👨‍💻 Алгоритм: 1⃣Инициализация указателей: Создать словарь для хранения узлов по их координатам (col, row). Создать очередь для обхода в ширину (BFS), содержащую начальную пару (root, (0, 0)). 2⃣Поиск пересечений: Выполнить BFS обход дерева. Для каждого узла сохранить его значение в словаре по ключу (col, row). Добавить левый потомок в очередь с координатами (row + 1, col - 1). Добавить правый потомок в очередь с координатами (row + 1, col + 1). 3⃣Возврат результата: Отсортировать ключи словаря по col и затем по row. Для каждого столбца, упорядочить узлы по row и значениям, и добавить их в результирующий список. 😎 Решение: class Solution { func verticalTraversal(_ root: TreeNode?) -> [[Int]] { var colTable = [Int: [(Int, Int)]]() var queue: [(TreeNode?, Int, Int)] = [(root, 0, 0)] while !queue.isEmpty { let (node, row, col) = queue.removeFirst() if let node = node { if colTable[col] != nil { colTable[col]!.append((row, node.val)) } else { colTable[col] = [(row, node.val)] } queue.append((node.left, row + 1, col - 1)) queue.append((node.right, row + 1, col + 1)) } } var result = [[Int]]() for key in colTable.keys.sorted() { colTable[key]!.sort { $0 < $1 } result.append(colTable[key]!.map { $0.1 }) } return result } } Ставь 👍 и забирай 📚 Базу знаний
74
14
Задача: 1258. Synonymous Sentences Сложность: medium Вам дан список эквивалентных пар строк synonyms, где synonyms[i] = [si, ti] означает, что si и ti являются эквивалентными строками. Вам также дан текст предложения. Верните все возможные синонимичные предложения, отсортированные лексикографически. Пример: Input: synonyms = [["happy","joy"],["sad","sorrow"],["joy","cheerful"]], text = "I am happy today but was sad yesterday" Output: ["I am cheerful today but was sad yesterday","I am cheerful today but was sorrow yesterday","I am happy today but was sad yesterday","I am happy today but was sorrow yesterday","I am joy today but was sad yesterday","I am joy today but was sorrow yesterday"] 👨‍💻 Алгоритм: 1⃣Построить граф синонимов, используя структуру данных, такую как Union-Find или просто с использованием DFS/BFS. 2⃣Пройти по каждому слову в предложении и найти все возможные синонимы. Сгенерировать все возможные комбинации предложений. 3⃣Отсортировать полученные предложения лексикографически. 😎 Решение: class Solution { func generateSentences(_ synonyms: [[String]], _ text: String) -> [String] { var graph = [String: Set<String>]() for pair in synonyms { graph[pair[0], default: Set()].insert(pair[1]) graph[pair[1], default: Set()].insert(pair[0]) } let words = text.split(separator: " ").map { String($0) } var synonymGroups = [[String]]() for word in words { synonymGroups.append(findSynonyms(graph, word)) } var sentences = [String]() var sentence = "" generate(&sentences, synonymGroups, &sentence, 0) return sentences.sorted() } private func findSynonyms(_ graph: [String: Set<String>], _ word: String) -> [String] { var synonyms = Set<String>() var stack = [word] while !stack.isEmpty { let w = stack.removeLast() if synonyms.insert(w).inserted { for neighbor in graph[w] ?? [] { stack.append(neighbor) } } } return Array(synonyms).sorted() } private func generate(_ sentences: inout [String], _ groups: [[String]], _ sentence: inout String, _ index: Int) { if index == groups.count { sentences.append(sentence.trimmingCharacters(in: .whitespaces)) return } for word in groups[index] { let original = sentence sentence += " " + word generate(&sentences, groups, &sentence, index + 1) sentence = original } } } Ставь 👍 и забирай 📚 Базу знаний
68
15
Задача: 903. Valid Permutations for DI Sequence Сложность: hard Вам дана строка s длины n, где s[i] либо: 'D' означает убывание, либо 'I' означает возрастание. Перестановка perm из n + 1 целых чисел всех целых чисел в диапазоне [0, n] называется допустимой, если для всех допустимых i: если s[i] == 'D', то perm[i] > perm[i + 1], а если s[i] == 'I', то perm[i] < perm[i + 1]. Верните количество допустимых перестановок perm. Поскольку ответ может быть большим, верните его по модулю 109 + 7. Пример: Input: s = "DID" Output: 5 👨‍💻 Алгоритм: 1⃣Создать двумерный массив dp, где dp[i][j] представляет количество допустимых перестановок длины i, оканчивающихся на j. 2⃣Заполнить массив dp, учитывая условия возрастания и убывания из строки s. 3⃣Вернуть сумму dp[n][j] для всех j, что даст количество допустимых перестановок длины n + 1. 😎 Решение: class Solution { func numPermsDISequence(_ s: String) -> Int { let MOD = 1_000_000_007 let n = s.count var dp = Array(repeating: Array(repeating: 0, count: n + 1), count: n + 1) dp[0][0] = 1 let sArray = Array(s) for i in 1...n { for j in 0...i { if sArray[i - 1] == "D" { dp[i][j] = (j..<i).reduce(0) { ($0 + dp[i - 1][$1]) % MOD } } else { dp[i][j] = (0..<j).reduce(0) { ($0 + dp[i - 1][$1]) % MOD } } } } return dp[n].reduce(0) { ($0 + $1) % MOD } } } Ставь 👍 и забирай 📚 Базу знаний
66
16
Задача: 897. Increasing Order Search Tree Сложность: easy Задав корень дерева двоичного поиска, перестройте дерево по порядку так, чтобы самый левый узел дерева теперь был корнем дерева, а каждый узел не имел левого и только одного правого дочернего узла. Пример: Input: root = [5,3,6,2,4,null,8,1,null,null,null,7,9] Output: [1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9] 👨‍💻 Алгоритм: 1⃣Выполнить обход дерева в порядке in-order, чтобы получить список узлов. 2⃣Перестроить дерево, устанавливая каждый узел из списка как правый дочерний элемент предыдущего узла и устанавливая левые дочерние элементы в null. 3⃣Вернуть новый корень дерева (первый элемент списка). 😎 Решение: 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 } } func increasingBST(_ root: TreeNode?) -> TreeNode? { var nodes: [TreeNode] = [] func inorder(_ node: TreeNode?) { guard let node = node else { return } inorder(node.left) nodes.append(node) inorder(node.right) } inorder(root) for i in 0..<nodes.count - 1 { nodes[i].left = nil nodes[i].right = nodes[i + 1] } nodes.last?.left = nil nodes.last?.right = nil return nodes.first } Ставь 👍 и забирай 📚 Базу знаний
62
17
Задача: 70. Climbing Stairs Сложность: easy Ты поднимаешься по лестнице. Чтобы добраться до вершины, нужно преодолеть n ступенек. Каждый раз ты можешь подняться на 1 или 2 ступеньки. Сколькими различными способами ты можешь добраться до вершины? Пример: Input: n = 2 Output: 2 Explanation: There are two ways to climb to the top. 1. 1 step + 1 step 2. 2 steps 👨‍💻 Алгоритм: 1⃣В этом методе грубой силы мы рассматриваем все возможные комбинации шагов, то есть 1 и 2, на каждом шаге. 2⃣На каждом шаге мы вызываем функцию climbStairs для шага 1 и шага 2, и возвращаем сумму возвращаемых значений обеих функций. 3⃣Формула вызова функции: climbStairs(i, n) = climbStairs(i+1, n) + climbStairs(i+2, n), где i определяет текущий шаг, а n — целевой шаг. 😎 Решение: func climbStairs(_ n: Int) -> Int { return climbStairsHelper(0, n) } func climbStairsHelper(_ i: Int, _ n: Int) -> Int { if i > n { return 0 } if i == n { return 1 } return climbStairsHelper(i + 1, n) + climbStairsHelper(i + 2, n) } Ставь 👍 и забирай 📚 Базу знаний
68
18
Задача: 292. Nim Game Сложность: easy Вы играете в следующую игру Nim со своим другом: Изначально на столе лежит куча камней. Вы и ваш друг поочередно делаете ходы, и вы ходите первым. Каждый ход игрок, чей ход, будет убирать от 1 до 3 камней из кучи. Тот, кто убирает последний камень, становится победителем. Дано n, количество камней в куче. Верните true, если вы можете выиграть игру, предполагая, что и вы, и ваш друг играете оптимально, иначе верните false. Пример: Input: n = 4 Output: false Explanation: These are the possible outcomes: 1. You remove 1 stone. Your friend removes 3 stones, including the last stone. Your friend wins. 2. You remove 2 stones. Your friend removes 2 stones, including the last stone. Your friend wins. 3. You remove 3 stones. Your friend removes the last stone. Your friend wins. In all outcomes, your friend wins. 👨‍💻 Алгоритм: 1⃣Определите базовый случай: Если количество камней n меньше или равно 3, вы всегда можете выиграть, убрав все камни. В этом случае верните true. 2⃣Анализ оставшихся камней: Если количество камней n делится на 4 без остатка (n % 4 == 0), вы не можете выиграть, так как независимо от вашего хода ваш друг всегда сможет оставить вам кратное 4 количество камней. В этом случае верните false. 3⃣Выигрышная стратегия: Если количество камней n не кратно 4 (n % 4 != 0), вы можете выиграть, оставляя вашему другу кратное 4 количество камней после вашего хода. В этом случае верните true. 😎 Решение: class Solution { func canWinNim(_ n: Int) -> Bool { return n % 4 != 0 } } Ставь 👍 и забирай 📚 Базу знаний
76
19
Задача: 409. Longest Palindrome Сложность: easy Если задана строка s, состоящая из строчных или прописных букв, верните длину самого длинного палиндрома, который можно построить из этих букв. Буквы чувствительны к регистру, например, "Aa" не считается палиндромом. Пример: Input: s = "abccccdd" Output: 7 👨‍💻 Алгоритм: 1⃣Создайте словарь для подсчета количества каждого символа в строке. 2⃣Пройдитесь по словарю и добавьте четное количество каждого символа к длине палиндрома. Если встречается нечетное количество символа, добавьте (count - 1) к длине палиндрома. 3⃣Если есть хотя бы один символ с нечетным количеством, добавьте 1 к длине палиндрома для центрального символа. 😎 Решение: func longestPalindrome(_ s: String) -> Int { var charCount = [Character: Int]() for char in s { charCount[char, default: 0] += 1 } var length = 0 var oddFound = false for count in charCount.values { if count % 2 == 0 { length += count } else { length += count - 1 oddFound = true } } return oddFound ? length + 1 : length } Ставь 👍 и забирай 📚 Базу знаний
78
20
Задача: 1243. Array Transformation Сложность: easy Если задан исходный массив arr, то каждый день вы создаете новый массив, используя массив предыдущего дня. В i-й день вы выполняете следующие операции над массивом дня i-1, чтобы получить массив дня i: если элемент меньше своего левого и правого соседа, то этот элемент увеличивается. Если элемент больше своего левого и правого соседа, то этот элемент уменьшается. Первый и последний элементы никогда не меняются. Через несколько дней массив не меняется. Верните этот окончательный массив. Пример: Input: arr = [6,2,3,4] Output: [6,3,3,4] 👨‍💻 Алгоритм: 1⃣Инициализация нового массива с такими же значениями, как у исходного массива. Циклически изменяем массив в соответствии с правилами, пока он не перестанет меняться. 2⃣Для каждого элемента массива проверяем, изменяется ли он в зависимости от его левого и правого соседей. Если элемент меньше своего левого и правого соседей, увеличиваем его. Если элемент больше своего левого и правого соседей, уменьшаем его. 3⃣Первый и последний элементы массива остаются неизменными. 😎 Решение: class Solution { func transformArray(_ arr: [Int]) -> [Int] { var arr = arr var changed = false repeat { changed = false var newArr = arr for i in 1..<arr.count - 1 { if arr[i] < arr[i - 1] && arr[i] < arr[i + 1] { newArr[i] += 1 changed = true } else if arr[i] > arr[i - 1] && arr[i] > arr[i + 1] { newArr[i] -= 1 changed = true } } arr = newArr } while changed return arr } } Ставь 👍 и забирай 📚 Базу знаний
79