uk
Feedback
C# | LeetCode

C# | LeetCode

Відкрити в Telegram

Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @easyoffer_adv

Показати більше
3 252
Підписники
-124 години
-87 днів
-3830 день

Триває завантаження даних...

Схожі канали
Немає даних
Виникли проблеми? Будь ласка, оновіть сторінку або зверніться до нашого support-менеджера.
Вхідні та вихідні згадування
---
---
---
---
---
---
Залучення підписників
липень '26
липень '26
+8
в 0 каналах
червень '26
+19
в 0 каналах
Get PRO
травень '26
+13
в 0 каналах
Get PRO
квітень '26
+23
в 0 каналах
Get PRO
березень '26
+21
в 0 каналах
Get PRO
лютий '26
+21
в 0 каналах
Get PRO
січень '26
+23
в 0 каналах
Get PRO
грудень '25
+24
в 0 каналах
Get PRO
листопад '25
+74
в 0 каналах
Get PRO
жовтень '25
+55
в 0 каналах
Get PRO
вересень '25
+46
в 0 каналах
Get PRO
серпень '25
+63
в 0 каналах
Get PRO
липень '25
+65
в 1 каналах
Get PRO
червень '25
+82
в 0 каналах
Get PRO
травень '25
+78
в 0 каналах
Get PRO
квітень '25
+111
в 0 каналах
Get PRO
березень '25
+230
в 2 каналах
Get PRO
лютий '25
+314
в 3 каналах
Get PRO
січень '25
+186
в 53 каналах
Get PRO
грудень '24
+64
в 0 каналах
Get PRO
листопад '24
+104
в 0 каналах
Get PRO
жовтень '24
+287
в 12 каналах
Get PRO
вересень '24
+1 084
в 331 каналах
Get PRO
серпень '24
+170
в 0 каналах
Get PRO
липень '24
+761
в 219 каналах
Get PRO
червень '24
+835
в 232 каналах
Дата
Залучення підписників
Згадування
Канали
15 липня0
14 липня0
13 липня0
12 липня0
11 липня0
10 липня+1
09 липня0
08 липня0
07 липня0
06 липня0
05 липня+1
04 липня+1
03 липня0
02 липня+3
01 липня+2
Дописи каналу
Задача: 678. Valid Parenthesis String Сложность: medium Создайте карту, которая позволяет выполнять следующие действия: Отображает строковый ключ на заданное значение. Возвращает сумму значений, у которых ключ имеет префикс, равный заданной строке. Реализуйте класс MapSum: Дана строка s, содержащая только три типа символов: '(', ')' и '*'. Вернуть true, если s является допустимой. Следующие правила определяют допустимую строку: Любая открывающая скобка '(' должна иметь соответствующую закрывающую скобку ')'. Любая закрывающая скобка ')' должна иметь соответствующую открывающую скобку '('. Открывающая скобка '(' должна идти перед соответствующей закрывающей скобкой ')'. '*' может рассматриваться как одна закрывающая скобка ')', одна открывающая скобка '(' или пустая строка "". Пример:
Input: s = "()"
Output: true
Example 2:
👨‍💻 Алгоритм: 1⃣Инициализировать 2D вектор memo размером s.size() x s.size() - 1, представляющий неинициализированное состояние. Вызвать вспомогательную функцию isValidString с начальными параметрами index = 0, openCount = 0 и строкой s. Вернуть результат isValidString. 2⃣Вспомогательная функция isValidString. Базовый случай: если index достиг конца строки (index == s.size.), вернуть true, если openCount равен 0 (все скобки сбалансированы), и false в противном случае. Проверить, был ли результат для текущего index и openCount уже вычислен (мемоизирован) в memo. Если да, вернуть мемоизированный результат. Инициализировать isValid как false. Если текущий символ s[index] равен '*': Попробовать трактовать '*' как '(' и вызвать isValidString рекурсивно с index + 1 и openCount + 1. Если рекурсивный вызов вернет true, обновить isValid на true. Если openCount не равен нулю, попробовать трактовать '*' как ')' и вызвать isValidString рекурсивно с index + 1 и openCount - 1. Если рекурсивный вызов вернет true, обновить isValid на true. Попробовать трактовать '*' как пустой символ и вызвать isValidString рекурсивно с index + 1 и тем же openCount. Если рекурсивный вызов вернет true, обновить isValid на true. 3⃣Продолжение функции isValidString. Если текущий символ s[index] равен '(': Вызвать isValidString рекурсивно с index + 1 и openCount + 1. Обновить isValid с результатом рекурсивного вызова. Если текущий символ s[index] равен ')': Если openCount не равен нулю (есть открытые скобки), вызвать isValidString рекурсивно с index + 1 и openCount - 1. Обновить isValid с результатом рекурсивного вызова. Мемоизировать результат isValid в memo[index][openCount]. Вернуть isValid. 😎 Решение:
using System;
using System.Collections.Generic;

public class Solution {
    public bool CheckValidString(string s) {
        int n = s.Length;
        int[][] memo = new int[n][];
        for (int i = 0; i < n; i++) {
            memo[i] = new int[n];
            Array.Fill(memo[i], -1);
        }
        return IsValidString(0, 0, s, memo);
    }

    private bool IsValidString(int index, int openCount, string str, int[][] memo) {
        if (index == str.Length) {
            return openCount == 0;
        }

        if (memo[index][openCount] != -1) {
            return memo[index][openCount] == 1;
        }

        bool isValid = false;

        if (str[index] == '*') {
            isValid = IsValidString(index + 1, openCount + 1, str, memo);
            if (openCount > 0) {
                isValid = isValid || IsValidString(index + 1, openCount - 1, str, memo);
            }
            isValid = isValid || IsValidString(index + 1, openCount, str, memo);
        } else if (str[index] == '(') {
            isValid = IsValidString(index + 1, openCount + 1, str, memo);
        } else if (openCount > 0) {
            isValid = IsValidString(index + 1, openCount - 1, str, memo);
        }

        memo[index][openCount] = isValid ? 1 : 0;
        return isValid;
    }
}
Ставь 👍 и забирай 📚 Базу знаний

2
Задача: 901. Online Stock Span Сложность: medium Разработайте алгоритм, который собирает ежедневные котировки цен на некоторые акции и возвращает размах цены этой акции за текущий день. Размах цены акции за один день - это максимальное количество дней подряд (начиная с этого дня и в обратном направлении), в течение которых цена акции была меньше или равна цене этого дня. Например, если цены акции за последние четыре дня равны [7,2,1,2], а цена акции сегодня равна 2, то размах сегодняшнего дня равен 4, поскольку, начиная с сегодняшнего дня, цена акции была меньше или равна 2 в течение 4 дней подряд. Также, если цена акции за последние четыре дня равна [7,34,1,2], а цена акции сегодня равна 8, то размах сегодняшнего дня равен 3, так как начиная с сегодняшнего дня цена акции была меньше или равна 8 в течение 3 дней подряд. Реализация класса StockSpanner: StockSpanner() Инициализирует объект класса. int next(int price) Возвращает размах цены акции, учитывая, что сегодняшняя цена равна price. Пример: Input ["StockSpanner", "next", "next", "next", "next", "next", "next", "next"] [[], [100], [80], [60], [70], [60], [75], [85]] Output [null, 1, 1, 1, 2, 1, 4, 6] 👨‍💻 Алгоритм: 1⃣Инициализировать стек для хранения пар значений (цена, размах) и переменную для текущего индекса. 2⃣Для метода next: Установить начальный размах текущего дня равным 1. Пока стек не пуст и верхний элемент стека имеет цену меньше или равную текущей цене: Добавить размах верхнего элемента стека к текущему размаху. Удалить верхний элемент стека. 3⃣Добавить текущую цену и размах на вершину стека. Вернуть текущий размах. 😎 Решение: using System; using System.Collections.Generic; public class StockSpanner { private Stack<Tuple<int, int>> stack; public StockSpanner() { stack = new Stack<Tuple<int, int>>(); } public int Next(int price) { int span = 1; while (stack.Count > 0 && stack.Peek().Item1 <= price) { span += stack.Pop().Item2; } stack.Push(Tuple.Create(price, span)); return span; } } Ставь 👍 и забирай 📚 Базу знаний
215
3
Задача: 753. Cracking the Safe Сложность: medium Имеется сейф, защищенный паролем. Пароль представляет собой последовательность из n цифр, каждая из которых может находиться в диапазоне [0, k - 1]. Сейф имеет особый способ проверки пароля. Например, правильный пароль - "345", а вы вводите "012345": после ввода 0 последние 3 цифры - "0", что неверно. После ввода 1 последние 3 цифры - "01", что неверно. После ввода 2 последние 3 цифры - "012", что неверно. После ввода 3 последние 3 цифры - "123", что неверно. После ввода 4 последние 3 цифры - "234", что неверно. После ввода 5 последние 3 цифры - "345", что верно, и сейф разблокируется. Верните любую строку минимальной длины, которая разблокирует сейф на определенном этапе ввода. Пример: Input: n = 1, k = 2 Output: "10" 👨‍💻 Алгоритм: 1⃣Создайте граф, где каждая вершина представляет собой строку длины n-1, а каждое ребро между двумя вершинами представляет собой добавление одной из цифр из диапазона [0, k-1]. 2⃣Используйте алгоритм Эйлерова пути или цикла для нахождения пути, который проходит через каждое ребро ровно один раз. 3⃣Составьте итоговую строку, которая включает начальную вершину и все добавленные цифры. 😎 Решение: using System.Collections.Generic; using System.Text; public class Solution { public string CrackSafe(int n, int k) { var seen = new HashSet<string>(); var result = new StringBuilder(); string startNode = new string('0', n - 1); Dfs(startNode, k, seen, result); result.Append(startNode); return result.ToString(); } private void Dfs(string node, int k, HashSet<string> seen, StringBuilder result) { for (int x = 0; x < k; x++) { string neighbor = node + x; if (!seen.Contains(neighbor)) { seen.Add(neighbor); Dfs(neighbor.Substring(1), k, seen, result); result.Append(x); } } } } Ставь 👍 и забирай 📚 Базу знаний
181
4
Задача: 1276. Number of Burgers with No Waste of Ingredients Сложность: medium Даны два целых числа tomatoSlices и cheeseSlices. Ингредиенты разных бургеров таковы: Jumbo Burger: 4 ломтика помидора и 1 ломтик сыра. Small Burger: 2 ломтика помидора и 1 ломтик сыра. Верните [total_jumbo, total_small] так, чтобы количество оставшихся tomatoSlices было равно 0, а количество оставшихся cheeseSlices было равно 0. Если невозможно сделать так, чтобы оставшиеся tomatoSlices и cheeseSlices были равны 0, верните []. Пример: Input: tomatoSlices = 16, cheeseSlices = 7 Output: [1,6] 👨‍💻 Алгоритм: 1⃣Проверьте, возможно ли решить задачу, убедившись, что tomatoSlices четно и находится в допустимых пределах. 2⃣Решите систему уравнений: 4J + 2S = tomatoSlices J + S = cheeseSlices 3⃣Если решение существует, верните его, иначе верните пустой список. 😎 Решение: public class Solution { public IList<int> NumOfBurgers(int tomatoSlices, int cheeseSlices) { if (tomatoSlices % 2 != 0 || tomatoSlices < 2 * cheeseSlices || tomatoSlices > 4 * cheeseSlices) { return new List<int>(); } int total_jumbo = (tomatoSlices - 2 * cheeseSlices) / 2; int total_small = cheeseSlices - total_jumbo; return new List<int> { total_jumbo, total_small }; } } Ставь 👍 и забирай 📚 Базу знаний
189
5
Задача: 567. Permutation in String Сложность: medium Даны две строки s1 и s2. Верните true, если s2 содержит перестановку s1, или false в противном случае. Другими словами, верните true, если одна из перестановок s1 является подстрокой s2. Пример: Input: s1 = "ab", s2 = "eidbaooo" Output: true Explanation: s2 contains one permutation of s1 ("ba"). 👨‍💻 Алгоритм: 1⃣Создать массив для подсчета символов в строке s1. Затем создать аналогичный массив для первых len(s1) символов строки s2. 2⃣Использовать скользящее окно для перемещения по строке s2. Для каждой позиции окна обновлять массив подсчета символов и сравнивать его с массивом для строки s1. 3⃣Если массивы совпадают на любом этапе, вернуть true. Если окно достигает конца строки s2 и совпадений не найдено, вернуть false. 😎 Решение: public class Solution { public bool CheckInclusion(string s1, string s2) { int s1Len = s1.Length, s2Len = s2.Length; if (s1Len > s2Len) return false; int[] s1Count = new int[26]; int[] s2Count = new int[26]; for (int i = 0; i < s1Len; i++) { s1Count[s1[i] - 'a']++; s2Count[s2[i] - 'a']++; } for (int i = 0; i < s2Len - s1Len; i++) { if (s1Count.SequenceEqual(s2Count)) return true; s2Count[s2[i] - 'a']--; s2Count[s2[i + s1Len] - 'a']++; } return s1Count.SequenceEqual(s2Count); } } Ставь 👍 и забирай 📚 Базу знаний
180
6
Задача: 1065. Index Pairs of a String Сложность: easy Дана строка text и массив строк words, верните массив всех пар индексов [i, j], таких что подстрока text[i...j] находится в words. Верните пары [i, j] в отсортированном порядке (то есть отсортируйте их по первой координате, а в случае совпадения сортируйте их по второй координате). Пример: Input: text = "thestoryofleetcodeandme", words = ["story","fleet","leetcode"] Output: [[3,7],[9,13],[10,17]] 👨‍💻 Алгоритм: 1⃣Поддерживайте хэш-набор слов. 2⃣Итерируйте i от 0 до text.length-1. Итерируйте j от i до text.length-1. Если подстрока text[i...j] принадлежит хэш-набору слов, добавьте пару [i, j] в ответ. 3⃣Верните ответ. 😎 Решение: public class Solution { public IList<IList<int>> IndexPairs(string text, string[] words) { var wordsSet = new HashSet<string>(words); var ans = new List<IList<int>>(); for (int i = 0; i < text.Length; i++) { for (int j = i; j < text.Length; j++) { if (wordsSet.Contains(text.Substring(i, j - i + 1))) { ans.Add(new List<int> { i, j }); } } } return ans; } } Ставь 👍 и забирай 📚 Базу знаний
170
7
Задача: 1231. Divide Chocolate Сложность: hard У вас есть одна шоколадка, состоящая из нескольких кусочков. Каждый кусочек имеет свою сладость, заданную массивом сладости. Вы хотите поделиться шоколадом со своими k друзьями, поэтому начинаете разрезать шоколадку на k + 1 кусочков с помощью k разрезов, каждый кусочек состоит из нескольких последовательных кусочков. Будучи щедрым, вы съедите кусочек с минимальной общей сладостью, а остальные кусочки отдадите своим друзьям. Найдите максимальную общую сладость кусочка, который вы можете получить, оптимально разрезав шоколадку. Пример: Input: sweetness = [1,2,3,4,5,6,7,8,9], k = 5 Output: 6 👨‍💻 Алгоритм: 1⃣Для решения задачи мы можем использовать метод двоичного поиска для определения максимальной минимальной сладости, которую можно получить. 2⃣Двоичный поиск: Мы будем искать ответ в диапазоне от минимальной сладости до суммы всех сладостей. Начнем с середины этого диапазона и проверим, можно ли разрезать шоколад таким образом, чтобы минимальная сладость была не менее этого значения. 3⃣Проверка делимости: Для каждой попытки значения сладости в двоичном поиске проверим, можем ли мы разрезать шоколад так, чтобы каждая из k+1 частей имела сладость не меньше текущего значения. 😎 Решение: public class Solution { public int MaximizeSweetness(int[] sweetness, int k) { bool CanDivide(int minSweetness) { int currentSum = 0, cuts = 0; foreach (var sweet in sweetness) { currentSum += sweet; if (currentSum >= minSweetness) { cuts++; currentSum = 0; } } return cuts >= k + 1; } int left = sweetness.Min(); int right = sweetness.Sum() / (k + 1); while (left < right) { int mid = (left + right + 1) / 2; if (CanDivide(mid)) { left = mid; } else { right = mid - 1; } } return left; } } Ставь 👍 и забирай 📚 Базу знаний
154
8
Задача: 1155. Number of Dice Rolls With Target Sum Сложность: medium У вас есть n кубиков, и на каждом кубике k граней, пронумерованных от 1 до k. Даны три целых числа n, k и target. Необходимо вернуть количество возможных способов (из общего количества kn способов) выбросить кубики так, чтобы сумма выпавших чисел равнялась target. Так как ответ может быть слишком большим, верните его по модулю 10^9 + 7. Пример: Input: n = 1, k = 6, target = 3 Output: 1 Explanation: You throw one die with 6 faces. There is only one way to get a sum of 3. 👨‍💻 Алгоритм: 1⃣Начните с: Индекс кубика diceIndex равен 0; это индекс кубика, который мы рассматриваем в данный момент. Сумма чисел на предыдущих кубиках currSum равна 0. Инициализируйте переменную ways значением 0. Итерируйтесь по значениям от 1 до k для каждого значения i. Если текущий кубик может иметь значение i, т.е. currSum после добавления i не превысит значение target, то обновите значение currSum и рекурсивно перейдите к следующему кубику. Добавьте значение, возвращенное этим рекурсивным вызовом, к ways. Иначе, если это значение невозможно, то выйдите из цикла, так как большие значения также не удовлетворят вышеуказанному условию. 2⃣Базовые случаи: Если мы перебрали все кубики, т.е. diceIndex = n, то проверьте, равна ли currSum значению target. 3⃣Верните значение ways и также сохраните его в таблице мемоизации memo, соответствующей текущему состоянию, определяемому diceIndex и currSum. 😎 Решение: public class Solution { private const int MOD = 1_000_000_007; private int WaysToTarget(int[][] memo, int diceIndex, int n, int currSum, int target, int k) { if (diceIndex == n) { return currSum == target ? 1 : 0; } if (memo[diceIndex][currSum] != -1) { return memo[diceIndex][currSum]; } int ways = 0; for (int i = 1; i <= Math.Min(k, target - currSum); i++) { ways = (ways + WaysToTarget(memo, diceIndex + 1, n, currSum + i, target, k)) % MOD; } memo[diceIndex][currSum] = ways; return ways; } public int NumRollsToTarget(int n, int k, int target) { int[][] memo = new int[n + 1][]; for (int i = 0; i <= n; i++) { memo[i] = new int[target + 1]; Array.Fill(memo[i], -1); } return WaysToTarget(memo, 0, n, 0, target, k); } } Ставь 👍 и забирай 📚 Базу знаний
160
9
Задача: 1062. Longest Repeating Substring Сложность: medium Дана строка s. Вернуть длину самой длинной повторяющейся подстроки. Если повторяющаяся подстрока отсутствует, вернуть 0. Пример: Input: s = "abcd" Output: 0 Explanation: There is no repeating substring. 👨‍💻 Алгоритм: 1⃣Перемещайте скользящее окно длиной L по строке длиной N. 2⃣Проверьте, находится ли строка в скользящем окне в хэш-наборе уже виденных строк. Если да, то повторяющаяся подстрока находится здесь. Если нет, сохраните строку из скользящего окна в хэш-наборе. 3⃣Очевидный недостаток этого подхода — большое потребление памяти в случае длинных строк. 😎 Решение: public class Solution { public int Search(int L, int n, string S) { var seen = new HashSet<string>(); for (int start = 0; start <= n - L; ++start) { string tmp = S.Substring(start, L); if (seen.Contains(tmp)) return start; seen.Add(tmp); } return -1; } public int LongestRepeatingSubstring(string S) { int n = S.Length; int left = 1, right = n; while (left <= right) { int L = left + (right - left) / 2; if (Search(L, n, S) != -1) { left = L + 1; } else { right = L - 1; } } return left - 1; } } Ставь 👍 и забирай 📚 Базу знаний
148
10
Задача: 1530. Number of Good Leaf Nodes Pairs Сложность: medium Вам дан корень бинарного дерева и целое число distance. Пара двух различных листовых узлов бинарного дерева называется хорошей, если длина кратчайшего пути между ними меньше или равна distance. Верните количество хороших пар листовых узлов в дереве. Пример: Input: root = [1,2,3,null,4], distance = 3 Output: 1 Explanation: The leaf nodes of the tree are 3 and 4 and the length of the shortest path between them is 3. This is the only good pair. 👨‍💻 Алгоритм: 1⃣Инициализируйте список смежности для преобразования дерева в граф и множество для хранения листовых узлов. Используйте вспомогательный метод traverseTree для обхода дерева, чтобы построить граф и найти листовые узлы. В параметрах поддерживайте текущий узел, а также родительский узел. Если текущий узел является листом, добавьте его в множество. В списке смежности добавьте текущий узел в список соседей родительского узла и наоборот. Рекурсивно вызовите traverseTree для левого и правого дочернего узла текущего узла. 2⃣Инициализируйте переменную ans для подсчета количества хороших пар листовых узлов. Итеративно переберите каждый листовой узел в множестве. Запустите BFS для текущего листового узла. BFS можно прервать досрочно, как только будут обнаружены все узлы, находящиеся на расстоянии от текущего листового узла. Увеличьте ans для каждого листового узла, найденного в каждом запуске BFS. 3⃣Верните ans / 2. Мы считаем каждую пару дважды, поэтому нужно разделить на 2, чтобы получить фактическое количество. 😎 Решение: public class Solution { public int CountPairs(TreeNode root, int distance) { var graph = new Dictionary<TreeNode, List<TreeNode>>(); var leafNodes = new HashSet<TreeNode>(); TraverseTree(root, null, graph, leafNodes); int ans = 0; foreach (var leaf in leafNodes) { var bfsQueue = new Queue<TreeNode>(); var seen = new HashSet<TreeNode>(); bfsQueue.Enqueue(leaf); seen.Add(leaf); for (int i = 0; i <= distance; i++) { int size = bfsQueue.Count; for (int j = 0; j < size; j++) { var currNode = bfsQueue.Dequeue(); if (leafNodes.Contains(currNode) && currNode != leaf) { ans++; } if (graph.ContainsKey(currNode)) { foreach (var neighbor in graph[currNode]) { if (!seen.Contains(neighbor)) { bfsQueue.Enqueue(neighbor); seen.Add(neighbor); } } } } } } return ans / 2; } private void TraverseTree(TreeNode currNode, TreeNode prevNode, Dictionary<TreeNode, List<TreeNode>> graph, HashSet<TreeNode> leafNodes) { if (currNode == null) { return; } if (currNode.left == null && currNode.right == null) { leafNodes.Add(currNode); } if (prevNode != null) { if (!graph.ContainsKey(prevNode)) { graph[prevNode] = new List<TreeNode>(); } graph[prevNode].Add(currNode); if (!graph.ContainsKey(currNode)) { graph[currNode] = new List<TreeNode>(); } graph[currNode].Add(prevNode); } TraverseTree(currNode.left, currNode, graph, leafNodes); TraverseTree(currNode.right, currNode, graph, leafNodes); } } Ставь 👍 и забирай 📚 Базу знаний
151
11
Задача: 845. Longest Mountain in Array Сложность: medium Вы можете вспомнить, что массив arr является горным массивом тогда и только тогда, когда: длина массива arr >= 3 Существует индекс i (счёт начинается с 0) такой, что: arr[0] < arr[1] < ... < arr[i - 1] < arr[i] arr[i] > arr[i + 1] > ... > arr[arr.length - 1] Дан целочисленный массив arr, верните длину самой длинной подпоследовательности, которая является горной. Верните 0, если такой подпоследовательности нет. Пример: Input: arr = [2,1,4,7,3,2,5] Output: 5 Explanation: The largest mountain is [1,4,7,3,2] which has length 5. 👨‍💻 Алгоритм: 1⃣Инициализируйте переменные для отслеживания текущего основания и максимальной длины горного массива. 2⃣Для каждого индекса, который может быть началом горного массива, определите пиковый элемент и найдите правую границу горного массива. 3⃣Если найден горный массив, обновите максимальную длину и переместите основание на конец текущего горного массива. 😎 Решение: class Solution { public: int longestMountain(vector<int>& A) { int N = A.size(); int ans = 0, base = 0; while (base < N) { int end = base; if (end + 1 < N && A[end] < A[end + 1]) { while (end + 1 < N && A[end] < A[end + 1]) end++; if (end + 1 < N && A[end] > A[end + 1]) { while (end + 1 < N && A[end] > A[end + 1]) end++; ans = max(ans, end - base + 1); } } base = max(end, base + 1); } return ans; } }; Ставь 👍 и забирай 📚 Базу знаний
167
12
АЙТИШНИКИ, ХВАТИТ сливать время на прилизанные новости и бесполезные курсы Проект «ИИнтеллигенция» стал главным каналом для т
АЙТИШНИКИ, ХВАТИТ сливать время на прилизанные новости и бесполезные курсы Проект «ИИнтеллигенция» стал главным каналом для тех, кто использует нейросети на уровне разработки, автоматизации и опенсорса, а не просто балуется в чатах. Здесь собирают только то, что реально экономит человеко-часы и работает в проде. 🎓 Готовые ИИ-сервисы, промпты и ИИ-агенты для автоматизации рутины 📚 Разборы полезных ИИ-инструментов, локальных LLM и опенсорс-репозиториев 🛠 Практические кейсы, гайды по деплою моделей и интеграции ИИ в пайплайны ⚡️ Технические ИТ-новости без маркетинговой воды и душных отчетов Обучение и прокачка в реальном времени: работа с API (Claude, GPT), локалки (Ollama, vLLM), автоматизация кода, опенсорс-утилиты, AI-агенты и др. Ценишь время и работаешь с ИИ, подпишись: @clucai
146
13
Задача: 1425. Constrained Subsequence Sum Сложность: hard Дан целочисленный массив nums и целое число k, верните максимальную сумму непустой подпоследовательности этого массива, такую, что для любых двух последовательных целых чисел в подпоследовательности nums[i] и nums[j], где i < j, выполняется условие j - i <= k. Подпоследовательность массива получается путем удаления некоторого количества элементов (может быть ноль) из массива, оставляя оставшиеся элементы в их исходном порядке. Пример: Input: nums = [10,2,-10,5,20], k = 2 Output: 37 Explanation: The subsequence is [10, 2, 5, 20]. 👨‍💻 Алгоритм: 1⃣Инициализируйте очередь queue и массив dp той же длины, что и nums. 2⃣Итерируйте i по индексам nums: Если i минус первый элемент queue больше k, удалите элемент из начала queue. Установите dp[i] как dp[queue.front()] + nums[i]. Если queue пуст, используйте 0 вместо dp[queue.front()]. Пока dp[queue.back()] меньше dp[i], удаляйте элементы с конца queue. Если dp[i] > 0, добавьте i в конец queue. 3⃣Верните максимальное значение в массиве dp. 😎 Решение: public class Solution { public int ConstrainedSubsetSum(int[] nums, int k) { Deque<int> queue = new LinkedList<int>(); int[] dp = new int[nums.Length]; int maxSum = int.MinValue; for (int i = 0; i < nums.Length; i++) { if (queue.Count > 0 && i - queue.First.Value > k) { queue.RemoveFirst(); } dp[i] = (queue.Count > 0 ? dp[queue.First.Value] : 0) + nums[i]; while (queue.Count > 0 && dp[queue.Last.Value] < dp[i]) { queue.RemoveLast(); } if (dp[i] > 0) { queue.AddLast(i); } maxSum = Math.Max(maxSum, dp[i]); } return maxSum; } } Ставь 👍 и забирай 📚 Базу знаний
200
14
Задача: 1406. Stone Game III Сложность: hard Алиса и Боб продолжают свои игры с кучами камней. Камни расположены в ряд, и каждый камень имеет ассоциированное значение, которое представлено целым числом в массиве stoneValue. Алиса и Боб ходят по очереди, начиная с Алисы. В свой ход каждый игрок может взять 1, 2 или 3 камня из первых оставшихся камней в ряду. Счет каждого игрока равен сумме значений взятых камней. Изначально счет каждого игрока равен 0. Цель игры — закончить с наивысшим счетом, и победителем становится игрок с наивысшим счетом, при этом возможна ничья. Игра продолжается, пока все камни не будут взяты. Предположим, что Алиса и Боб играют оптимально. Верните "Alice", если Алиса выиграет, "Bob", если выиграет Боб, или "Tie", если они закончат игру с одинаковым счетом. Пример: Input: stoneValue = [1,2,3,7] Output: "Bob" Explanation: Alice will always lose. Her best move will be to take three piles and the score become 6. Now the score of Bob is 7 and Bob wins. 👨‍💻 Алгоритм: 1⃣Инициализируйте массив dp размером n+1 и установите dp[n] в 0. 2⃣Итеративно обновляйте dp[i] для всех i от n-1 до 0, вычисляя максимальную разницу в баллах, которые могут получить игроки при оптимальной игре. 3⃣Определите победителя, сравнивая dp[0] с 0: если больше, победит Алиса; если меньше, победит Боб; если равно, будет ничья. 😎 Решение: public class Solution { public string StoneGameIII(int[] stoneValue) { int n = stoneValue.Length; int[] dp = new int[n + 1]; for (int i = n - 1; i >= 0; --i) { dp[i] = stoneValue[i] - dp[i + 1]; if (i + 2 <= n) { dp[i] = Math.Max(dp[i], stoneValue[i] + stoneValue[i + 1] - dp[i + 2]); } if (i + 3 <= n) { dp[i] = Math.Max(dp[i], stoneValue[i] + stoneValue[i + 1] + stoneValue[i + 2] - dp[i + 3]); } } if (dp[0] > 0) return "Alice"; if (dp[0] < 0) return "Bob"; return "Tie"; } } Ставь 👍 и забирай 📚 Базу знаний
211
15
Задача: 94. Binary Tree Inorder Traversal Сложность: easy Дан корень бинарного дерева. Верните обход значений его узлов в сим
Задача: 94. Binary Tree Inorder Traversal Сложность: easy Дан корень бинарного дерева. Верните обход значений его узлов в симметричном порядке. Пример: Input: root = [1,null,2,3] Output: [1,3,2] 👨‍💻 Алгоритм: 1⃣Используйте рекурсивную вспомогательную функцию Helper, чтобы обойти дерево. 2⃣В каждом вызове сначала рекурсивно вызывайте левое поддерево. 3⃣Затем укажите значение текущего узла в результате и рекурсивно вызовите правое поддерево. 😎 Решение: public class Solution { List<int> res = new List<int>(); public IList<int> InorderTraversal(TreeNode root) { Helper(root); return res; } public void Helper(TreeNode root) { if (root != null) { Helper(root.left); res.Add(root.val); Helper(root.right); } } } Ставь 👍 и забирай 📚 Базу знаний
187
16
Задача: 1180. Count Substrings with Only One Distinct Letter Сложность: easy Дана строка s. Верните количество подстрок, которые содержат только одну уникальную букву. Пример: Input: s = "aaaba" Output: 8 Explanation: The substrings with one distinct letter are "aaa", "aa", "a", "b". "aaa" occurs 1 time. "aa" occurs 2 times. "a" occurs 4 times. "b" occurs 1 time. So the answer is 1 + 2 + 4 + 1 = 8. 👨‍💻 Алгоритм: 1⃣Инициализируйте целочисленную переменную total для подсчета количества подстрок, а также два указателя left и right, которые отмечают начало и конец подстроки, содержащей только одну уникальную букву. 2⃣Итерируйте по строке S: Если мы не достигли конца и новый символ S[right] такой же, как и начальный символ S[left], увеличьте right на 1 для дальнейшего исследования строки S; в противном случае вычислите длину подстроки как right - left и примените формулу суммы арифметической последовательности; не забудьте установить right в left для начала исследования новой подстроки. 3⃣После завершения итерации добавьте к total количество подстрок для последнего сегмента, если он не был учтен. Верните значение total. 😎 Решение: public class Solution { public int CountLetters(string S) { int total = 0; int left = 0; for (int right = 0; right <= S.Length; right++) { if (right == S.Length || S[left] != S[right]) { int lenSubstring = right - left; total += (1 + lenSubstring) * lenSubstring / 2; left = right; } } return total; } } Ставь 👍 и забирай 📚 Базу знаний
217
17
Задача: 1279. Traffic Light Controlled Intersection Сложность: easy Здесь есть пересечение двух дорог. Первая дорога - это дорога A, по которой автомобили движутся с севера на юг в направлении 1 и с юга на север в направлении 2. Вторая дорога - дорога B, по которой машины едут с запада на восток в направлении 3 и с востока на запад в направлении 4. На каждой дороге перед перекрестком есть светофор. Зеленый означает, что автомобили могут пересекать перекресток в обоих направлениях. Красный означает, что автомобили в обоих направлениях не могут пересекать перекресток и должны ждать, пока загорится зеленый свет. Светофор не может гореть зеленым одновременно на обеих дорогах. Это значит, что когда на дороге А горит зеленый свет, на дороге Б он красный, а когда на дороге Б горит зеленый свет, на дороге А он красный. Изначально на дороге A горит зеленый сигнал светофора, а на дороге B - красный. Когда на одной дороге горит зеленый свет, все автомобили могут пересекать перекресток в обоих направлениях, пока на другой дороге не загорится зеленый.Два автомобиля, движущиеся по разным дорогам, не должны пересекать перекресток одновременно. Разработайте систему управления светофором на этом перекрестке без тупиков. Реализуйте функцию void carArrived(carId, roadId, direction, turnGreen, crossCar), где: carId - идентификатор автомобиля, который приехал. roadId - идентификатор дороги, по которой едет автомобиль. direction - направление движения автомобиля. turnGreen - функция, которую можно вызвать, чтобы переключить светофор на зеленый свет на текущей дороге. crossCar - функция, которую можно вызвать, чтобы позволить текущему автомобилю пересечь перекресток. Ваш ответ считается правильным, если он позволяет избежать тупика на перекрестке.Переключение светофора на зеленый свет на дороге, где он уже был зеленым, считается неправильным ответом. Пример: Input: cars = [1,2,3,4,5], directions = [2,4,3,3,1], arrivalTimes = [10,20,30,40,40] Output: [ "Car 1 Has Passed Road A In Direction 2", // Traffic light on road A is green, car 1 can cross the intersection. "Traffic Light On Road B Is Green", // Car 2 requests green light for road B. "Car 2 Has Passed Road B In Direction 4", // Car 2 crosses as the light is green on road B now. "Car 3 Has Passed Road B In Direction 3", // Car 3 crosses as the light is green on road B now. "Traffic Light On Road A Is Green", // Car 5 requests green light for road A. "Car 5 Has Passed Road A In Direction 1", // Car 5 crosses as the light is green on road A now. "Traffic Light On Road B Is Green", // Car 4 requests green light for road B. Car 4 blocked until car 5 crosses and then traffic light is green on road B. "Car 4 Has Passed Road B In Direction 3" // Car 4 crosses as the light is green on road B now. ] 👨‍💻 Алгоритм: 1⃣Если на дороге, по которой едет автомобиль, уже зеленый свет, вызываем функцию crossCar. 2⃣Если на дороге, по которой едет автомобиль, красный свет, вызываем функцию turnGreen, чтобы переключить свет на зеленый, и затем вызываем функцию crossCar. 3⃣Обеспечиваем, что функции turnGreen и crossCar вызываются атомарно для предотвращения гонок и тупиков 😎 Решение: using System; using System.Threading; public class TrafficLight { private int greenRoad = 1; private readonly object lockObj = new object(); public void CarArrived( int carId, int roadId, int direction, Action turnGreen, Action crossCar ) { lock (lockObj) { if (greenRoad != roadId) { turnGreen(); greenRoad = roadId; } crossCar(); } } } Ставь 👍 и забирай 📚 Базу знаний
196
18
Задача: 412. Fizz Buzz Сложность: easy Учитывая целое число n, верните строковый массив answer (с индексом 1), где: answer[i] == "FizzBuzz", если i делится на 3 и 5. answer[i] == "Fizz", если i делится на 3. answer[i] == "Buzz", если i делится на 5. answer[i] == i (как строка), если ни одно из перечисленных условий не верно. Пример: Input: nums = [1,2,2] Output: [[],[1],[1,2],[1,2,2],[2],[2,2]] 👨‍💻 Алгоритм: 1⃣Создайте пустой список для хранения результата. 2⃣Пройдите по всем числам от 1 до n и для каждого числа выполните проверку: Если число делится на 3 и на 5, добавьте "FizzBuzz". Если число делится на 3, добавьте "Fizz". Если число делится на 5, добавьте "Buzz". Если ни одно из условий не выполнено, добавьте само число как строку. 3⃣Верните полученный список. 😎 Решение: using System; using System.Collections.Generic; public class Solution { public IList<string> FizzBuzz(int n) { List<string> answer = new List<string>(); for (int i = 1; i <= n; i++) { if (i % 3 == 0 && i % 5 == 0) { answer.Add("FizzBuzz"); } else if (i % 3 == 0) { answer.Add("Fizz"); } else if (i % 5 == 0) { answer.Add("Buzz"); } else { answer.Add(i.ToString()); } } return answer; } } Ставь 👍 и забирай 📚 Базу знаний
221
19
Задача: 945. Minimum Increment to Make Array Unique Сложность: medium Вам дан целочисленный массив nums. За один ход вы можете выбрать индекс i, где 0 <= i < nums.length, и увеличить nums[i] на 1. Верните минимальное количество ходов, чтобы каждое значение в nums было уникальным. Тестовые примеры генерируются так, чтобы ответ умещался в 32-битное целое число. Пример: Input: nums = [1,2,2] Output: 1 👨‍💻 Алгоритм: 1⃣Отсортировать массив nums. Инициализировать переменную moves для подсчета количества ходов. 2⃣Пройти по массиву и для каждого элемента, начиная со второго: Если текущий элемент меньше или равен предыдущему элементу, увеличить текущий элемент до значения предыдущего элемента + 1 и обновить счетчик ходов. 3⃣Вернуть общее количество ходов. 😎 Решение: public class Solution { public int MinIncrementForUnique(int[] nums) { Array.Sort(nums); int moves = 0; for (int i = 1; i < nums.Length; i++) { if (nums[i] <= nums[i - 1]) { moves += nums[i - 1] + 1 - nums[i]; nums[i] = nums[i - 1] + 1; } } return moves; } } Ставь 👍 и забирай 📚 Базу знаний
231
20
Задача: 1036. Escape a Large Maze Сложность: hard Имеется сетка размером 1 миллион на 1 миллион на плоскости XY, координаты каждого квадрата сетки - (x, y). Мы начинаем с исходного квадрата = [sx, sy] и хотим достичь цели = [tx, ty]. Существует также массив заблокированных квадратов, где каждый заблокированный[i] = [xi, yi] представляет собой заблокированный квадрат с координатами (xi, yi). Каждый ход мы можем пройти один квадрат на север, восток, юг или запад, если квадрат не находится в массиве заблокированных квадратов. Нам также не разрешается выходить за пределы сетки. Возвращается true тогда и только тогда, когда можно достичь целевого квадрата из исходного квадрата с помощью последовательности правильных ходов. Пример: Input: blocked = [[0,1],[1,0]], source = [0,0], target = [0,2] Output: false 👨‍💻 Алгоритм: 1⃣Обработка входных данных: Загрузите координаты исходного квадрата sx, sy, целевого квадрата tx, ty и список заблокированных квадратов blocked. 2⃣Проверка простого случая: Если список blocked пуст, верните true, так как путь не будет заблокирован. Проверка начальной или целевой клетки: Если исходная или целевая клетка заблокированы, верните false. 3⃣Поиск пути с использованием BFS или DFS: Используйте алгоритм поиска в ширину (BFS) или поиска в глубину (DFS) для поиска пути от sx, sy до tx, ty, избегая заблокированных клеток. Если обнаружен путь, верните true, в противном случае верните false. 😎 Решение: public class Solution { public bool IsEscapePossible(int[][] blocked, int[] source, int[] target) { var blockedSet = new HashSet<(int, int)>(blocked.Select(b => (b[0], b[1]))); var src = (source[0], source[1]); var tgt = (target[0], target[1]); if (blockedSet.Contains(src) || blockedSet.Contains(tgt)) return false; var directions = new (int, int)[] { (0, 1), (1, 0), (0, -1), (-1, 0) }; int maxArea = blocked.Length * (blocked.Length - 1) / 2; bool Bfs((int, int) start, (int, int) end) { var queue = new Queue<(int, int)>(); queue.Enqueue(start); var visited = new HashSet<(int, int)> { start }; while (queue.Count > 0) { if (visited.Count > maxArea) return true; var (x, y) = queue.Dequeue(); foreach (var (dx, dy) in directions) { var nx = x + dx; var ny = y + dy; var next = (nx, ny); if (nx >= 0 && nx < 1_000_000 && ny >= 0 && ny < 1_000_000 && !visited.Contains(next) && !blockedSet.Contains(next)) { if (next == end) return true; queue.Enqueue(next); visited.Add(next); } } } return false; } return Bfs(src, tgt) && Bfs(tgt, src); } } Ставь 👍 и забирай 📚 Базу знаний
209