Задача: 1382. Balance a Binary Search Tree
Сложность: medium
Дан корень бинарного дерева поиска. Верните сбалансированное бинарное дерево поиска с теми же значениями узлов. Если существует более одного ответа, верните любой из них.
Бинарное дерево поиска считается сбалансированным, если глубина двух поддеревьев каждого узла никогда не отличается более чем на 1.
Пример:
👨💻 Алгоритм:
1⃣Инициализация. Создайте пустой список inorder для хранения значений узлов после обхода в порядке возрастания.
2⃣Выполнение обхода в порядке возрастания. Обойдите бинарное дерево поиска (BST) и заполните список inorder значениями узлов в отсортированном порядке.
3⃣Перестроение сбалансированного BST. Определите рекурсивную функцию createBalancedBST, которая принимает список inorder, начальный индекс и конечный индекс в качестве параметров. Если начальный индекс больше конечного, верните null (или эквивалент). Вычислите средний индекс как середину текущего диапазона. Создайте новый узел дерева со значением в среднем индексе. Рекурсивно создайте левое поддерево, используя левую половину текущего диапазона. Рекурсивно создайте правое поддерево, используя правую половину текущего диапазона. Верните корень вновь построенного сбалансированного BST.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан корень бинарного дерева поиска. Верните сбалансированное бинарное дерево поиска с теми же значениями узлов. Если существует более одного ответа, верните любой из них.
Бинарное дерево поиска считается сбалансированным, если глубина двух поддеревьев каждого узла никогда не отличается более чем на 1.
Пример:
Input: root = [1,null,2,null,3,null,4,null,null]
Output: [2,1,3,null,null,null,4]
Explanation: This is not the only correct answer, [3,1,4,null,2] is also correct.
👨💻 Алгоритм:
1⃣Инициализация. Создайте пустой список inorder для хранения значений узлов после обхода в порядке возрастания.
2⃣Выполнение обхода в порядке возрастания. Обойдите бинарное дерево поиска (BST) и заполните список inorder значениями узлов в отсортированном порядке.
3⃣Перестроение сбалансированного BST. Определите рекурсивную функцию createBalancedBST, которая принимает список inorder, начальный индекс и конечный индекс в качестве параметров. Если начальный индекс больше конечного, верните null (или эквивалент). Вычислите средний индекс как середину текущего диапазона. Создайте новый узел дерева со значением в среднем индексе. Рекурсивно создайте левое поддерево, используя левую половину текущего диапазона. Рекурсивно создайте правое поддерево, используя правую половину текущего диапазона. Верните корень вновь построенного сбалансированного BST.
😎 Решение:
class Solution:
def balanceBST(self, root: TreeNode) -> TreeNode:
if not root:
return None
vineHead = TreeNode(0)
vineHead.right = root
current = vineHead
while current.right:
if current.right.left:
self.rightRotate(current, current.right)
else:
current = current.right
nodeCount = 0
current = vineHead.right
while current:
nodeCount += 1
current = current.right
m = 2 ** (nodeCount + 1).bit_length() - 1
self.makeRotations(vineHead, nodeCount - m)
while m > 1:
m //= 2
self.makeRotations(vineHead, m)
return vineHead.right
def rightRotate(self, parent, node):
tmp = node.left
node.left = tmp.right
tmp.right = node
parent.right = tmp
def leftRotate(self, parent, node):
tmp = node.right
node.right = tmp.left
tmp.left = node
parent.right = tmp
def makeRotations(self, vineHead, count):
current = vineHead
for _ in range(count):
tmp = current.right
self.leftRotate(current, tmp)
current = current.right
Ставь 👍 и забирай 📚 Базу знаний
Задача: 973. K Closest Points to Origin
Сложность: medium
Дан массив точек, где points[i] = [xi, yi] представляет собой точку на плоскости X-Y, и целое число k. Верните k точек, ближайших к началу координат (0, 0).
Расстояние между двумя точками на плоскости X-Y является евклидовым расстоянием (то есть √((x1 - x2)² + (y1 - y2)²)).
Вы можете вернуть ответ в любом порядке. Гарантируется, что ответ будет уникальным (за исключением порядка).
Пример:
👨💻 Алгоритм:
1⃣Отсортируйте массив с помощью функции компаратора.
2⃣Функция компаратора будет использовать уравнение квадратного евклидова расстояния для сравнения двух точек.
3⃣Верните первые k элементов массива.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив точек, где points[i] = [xi, yi] представляет собой точку на плоскости X-Y, и целое число k. Верните k точек, ближайших к началу координат (0, 0).
Расстояние между двумя точками на плоскости X-Y является евклидовым расстоянием (то есть √((x1 - x2)² + (y1 - y2)²)).
Вы можете вернуть ответ в любом порядке. Гарантируется, что ответ будет уникальным (за исключением порядка).
Пример:
Input: points = [[1,3],[-2,2]], k = 1
Output: [[-2,2]]
Explanation:
The distance between (1, 3) and the origin is sqrt(10).
The distance between (-2, 2) and the origin is sqrt(8).
Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.
We only want the closest k = 1 points from the origin, so the answer is just [[-2,2]].
👨💻 Алгоритм:
1⃣Отсортируйте массив с помощью функции компаратора.
2⃣Функция компаратора будет использовать уравнение квадратного евклидова расстояния для сравнения двух точек.
3⃣Верните первые k элементов массива.
😎 Решение:
class Solution:
def kClosest(self, points: list[list[int]], k: int) -> list[list[int]]:
points.sort(key=self.squaredDistance)
return points[:k]
def squaredDistance(self, point: list[int]) -> int:
return point[0] ** 2 + point[1] ** 2
Ставь 👍 и забирай 📚 Базу знаний
Задача: 990. Satisfiability of Equality Equations
Сложность: medium
Дан массив строк equations, представляющий отношения между переменными, где каждая строка equations[i] имеет длину 4 и принимает одну из двух форм: "xi==yi" или "xi!=yi". Здесь xi и yi - это строчные буквы (не обязательно разные), представляющие имена переменных из одной буквы.
Верните true, если возможно назначить целые числа именам переменных таким образом, чтобы удовлетворить всем заданным уравнениям, или false в противном случае.
Пример:
👨💻 Алгоритм:
1⃣Создание графа для уравнений "==":
Создайте структуру данных для объединения (Union-Find) для обработки уравнений равенства.
Пройдите через массив equations и для каждого уравнения типа "xi==yi" объедините соответствующие переменные.
2⃣Проверка уравнений "!=":
Пройдите через массив equations и для каждого уравнения типа "xi!=yi" проверьте, принадлежат ли переменные к одной и той же группе в структуре объединения. Если принадлежат, верните false.
3⃣Возврат результата:
Если после проверки всех уравнений "xi!=yi" не было обнаружено противоречий, верните true.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Дан массив строк equations, представляющий отношения между переменными, где каждая строка equations[i] имеет длину 4 и принимает одну из двух форм: "xi==yi" или "xi!=yi". Здесь xi и yi - это строчные буквы (не обязательно разные), представляющие имена переменных из одной буквы.
Верните true, если возможно назначить целые числа именам переменных таким образом, чтобы удовлетворить всем заданным уравнениям, или false в противном случае.
Пример:
Input: equations = ["b==a","a==b"]
Output: true
Explanation: We could assign a = 1 and b = 1 to satisfy both equations.
👨💻 Алгоритм:
1⃣Создание графа для уравнений "==":
Создайте структуру данных для объединения (Union-Find) для обработки уравнений равенства.
Пройдите через массив equations и для каждого уравнения типа "xi==yi" объедините соответствующие переменные.
2⃣Проверка уравнений "!=":
Пройдите через массив equations и для каждого уравнения типа "xi!=yi" проверьте, принадлежат ли переменные к одной и той же группе в структуре объединения. Если принадлежат, верните false.
3⃣Возврат результата:
Если после проверки всех уравнений "xi!=yi" не было обнаружено противоречий, верните true.
😎 Решение:
class Solution:
def equationsPossible(self, equations: List[str]) -> bool:
uf = UnionFind(26)
for eq in equations:
if eq[1] == '=':
x = ord(eq[0]) - ord('a')
y = ord(eq[3]) - ord('a')
uf.union(x, y)
for eq in equations:
if eq[1] == '!':
x = ord(eq[0]) - ord('a')
y = ord(eq[3]) - ord('a')
if uf.connected(x, y):
return False
return True
class UnionFind:
def __init__(self, size):
self.parent = list(range(size))
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, x, y):
rootX = self.find(x)
rootY = self.find(y)
if rootX != rootY:
self.parent[rootX] = rootY
def connected(self, x, y):
return self.find(x) == self.find(y)
Ставь 👍 и забирай 📚 Базу знаний
Задача: 543. Diameter of Binary Tree
Сложность: easy
Учитывая корень бинарного дерева, вернуть длину диаметра дерева.
Диаметр бинарного дерева — это длина самого длинного пути между любыми двумя узлами в дереве. Этот путь может проходить или не проходить через корень.
Длина пути между двумя узлами представлена числом ребер между ними.
Пример:
👨💻 Алгоритм:
1⃣Инициализируйте целочисленную переменную diameter для отслеживания самого длинного пути, найденного с помощью DFS.
2⃣Реализуйте рекурсивную функцию longestPath, которая принимает TreeNode в качестве входных данных и рекурсивно исследует дерево: Если узел равен None, вернуть 0. Рекурсивно исследовать левые и правые дочерние узлы, возвращая длины путей leftPath и rightPath. Если сумма leftPath и rightPath больше текущего diameter, обновить diameter. Вернуть большее из leftPath и rightPath плюс 1.
3⃣Вызвать longestPath с root.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Учитывая корень бинарного дерева, вернуть длину диаметра дерева.
Диаметр бинарного дерева — это длина самого длинного пути между любыми двумя узлами в дереве. Этот путь может проходить или не проходить через корень.
Длина пути между двумя узлами представлена числом ребер между ними.
Пример:
Input: root = [1,2]
Output: 1
👨💻 Алгоритм:
1⃣Инициализируйте целочисленную переменную diameter для отслеживания самого длинного пути, найденного с помощью DFS.
2⃣Реализуйте рекурсивную функцию longestPath, которая принимает TreeNode в качестве входных данных и рекурсивно исследует дерево: Если узел равен None, вернуть 0. Рекурсивно исследовать левые и правые дочерние узлы, возвращая длины путей leftPath и rightPath. Если сумма leftPath и rightPath больше текущего diameter, обновить diameter. Вернуть большее из leftPath и rightPath плюс 1.
3⃣Вызвать longestPath с root.
😎 Решение:
class Solution:
def __init__(self):
self.diameter = 0
def diameterOfBinaryTree(self, root):
self.diameter = 0
self.longestPath(root)
return self.diameter
def longestPath(self, node):
if not node:
return 0
leftPath = self.longestPath(node.left)
rightPath = self.longestPath(node.right)
self.diameter = max(self.diameter, leftPath + rightPath)
return max(leftPath, rightPath) + 1
Ставь 👍 и забирай 📚 Базу знаний
Задача: 1137. N-th Tribonacci Number
Сложность: easy
Трибоначчи последовательность Tn определяется следующим образом:
T0 = 0, T1 = 1, T2 = 1, и Tn+3 = Tn + Tn+1 + Tn+2 для n >= 0.
Дано n, вернуть значение Tn.
Пример:
👨💻 Алгоритм:
1⃣Если n < 3, вернуть значение n-го терма, как указано в описании задачи.
2⃣Инициализировать a, b и c как базовые случаи. Установить a = 0, b = 1, c = 1.
3⃣Для следующих n - 2 шагов обновлять a, b, c следующим образом: a = b, b = c, c = a + b + c. Вернуть c.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Трибоначчи последовательность Tn определяется следующим образом:
T0 = 0, T1 = 1, T2 = 1, и Tn+3 = Tn + Tn+1 + Tn+2 для n >= 0.
Дано n, вернуть значение Tn.
Пример:
Input: n = 4
Output: 4
Explanation:
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4
👨💻 Алгоритм:
1⃣Если n < 3, вернуть значение n-го терма, как указано в описании задачи.
2⃣Инициализировать a, b и c как базовые случаи. Установить a = 0, b = 1, c = 1.
3⃣Для следующих n - 2 шагов обновлять a, b, c следующим образом: a = b, b = c, c = a + b + c. Вернуть c.
😎 Решение:
class Solution:
def tribonacci(self, n: int) -> int:
if n < 3:
return 1 if n > 0 else 0
a, b, c = 0, 1, 1
for _ in range(n - 2):
a, b, c = b, c, a + b + c
return c
Ставь 👍 и забирай 📚 Базу знаний
Задача: 26. Remove Duplicates from Sorted Array
Сложность: easy
Учитывая целочисленный массив чисел, отсортированный в неубывающем порядке, удалите дубликаты на месте так, чтобы каждый уникальный элемент появлялся только один раз. Относительный порядок элементов должен оставаться неизменным. Затем верните количество уникальных элементов в числах.
Считайте, что количество уникальных элементов чисел равно k. Чтобы вас приняли, вам нужно сделать следующее:
- Измените массив nums так, чтобы первые k элементов nums содержали уникальные элементы в том порядке, в котором они присутствовали в nums изначально. Остальные элементы nums не важны, как и размер nums.
- Вернуть k.
Пример:
👨💻 Алгоритм:
1️⃣Используем два указателя: один для уникальных элементов, другой для прохода по массиву.
2️⃣Перебираем массив, добавляя уникальные элементы на место.
3️⃣Возвращаем количество уникальных элементов.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Учитывая целочисленный массив чисел, отсортированный в неубывающем порядке, удалите дубликаты на месте так, чтобы каждый уникальный элемент появлялся только один раз. Относительный порядок элементов должен оставаться неизменным. Затем верните количество уникальных элементов в числах.
Считайте, что количество уникальных элементов чисел равно k. Чтобы вас приняли, вам нужно сделать следующее:
- Измените массив nums так, чтобы первые k элементов nums содержали уникальные элементы в том порядке, в котором они присутствовали в nums изначально. Остальные элементы nums не важны, как и размер nums.
- Вернуть k.
Пример:
Input: nums = [1,1,2]
Output: 2, nums = [1,2,_]
👨💻 Алгоритм:
1️⃣Используем два указателя: один для уникальных элементов, другой для прохода по массиву.
2️⃣Перебираем массив, добавляя уникальные элементы на место.
3️⃣Возвращаем количество уникальных элементов.
😎 Решение:
from typing import List
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
i = 0
while i < len(nums) - 1:
if nums[i] == nums[i + 1]:
nums.pop(i + 1)
else:
i += 1
return len(nums)
Ставь 👍 и забирай 📚 Базу знаний
Один из главных мифов вокруг ИИ-кодинга: достаточно найти правильный промпт — и модель начнет писать хороший код
Но на практике два разработчика могут отправить одинаковый запрос: «создай API для пользователей» — и получить совершенно разный результат. Один получит аккуратный FastAPI-сервис с типами, тестами и обработкой ошибок. Другой — код, который придется переписывать после первого изменения.
Причина часто не в модели.
LLM (большие языковые модели) не знает, как устроен ваш проект: какие архитектурные решения приняты, какие стандарты действуют и что команда считает качественным результатом.
Поэтому стоит выстраивать вокруг ИИ тот же инженерный слой, который уже есть в обычной разработке: правила проекта, чек-листы, автоматические проверки и понятные критерии качества.
На бесплатном вебинаре karpovꓸcourses «ИИ-агенты и профессиональная разработка на Python» Алексей Жиряков покажет вживую, почему ИИ-код ломается в реальных проектах и как это исправлять.
Алексей — исполнительный директор в Сбере, занимается развитием генеративного ИИ, а до этого более 15 лет работал в backend-разработке и руководил инженерными командами.
Будет живое демо поверх готового репозитория: как настроить процесс, получить более чистый типизированный код и использовать продакшен-подход вроде связки «дешевая модель пишет — дорогая ревьюит», которая помогает снижать стоимость генерации.
Присоединяйтесь по ссылке, а после регистрации вы получите гайд «Почему ваш ИИ пишет не то: LLM против ИИ-агента»: https://clc.to/erid_2W5zFGkYPEH
Реклама. ООО «КАРПОВ КУРСЫ». ИНН 7811764627. erid: 2W5zFGkYPEH
Но на практике два разработчика могут отправить одинаковый запрос: «создай API для пользователей» — и получить совершенно разный результат. Один получит аккуратный FastAPI-сервис с типами, тестами и обработкой ошибок. Другой — код, который придется переписывать после первого изменения.
Причина часто не в модели.
LLM (большие языковые модели) не знает, как устроен ваш проект: какие архитектурные решения приняты, какие стандарты действуют и что команда считает качественным результатом.
Поэтому стоит выстраивать вокруг ИИ тот же инженерный слой, который уже есть в обычной разработке: правила проекта, чек-листы, автоматические проверки и понятные критерии качества.
На бесплатном вебинаре karpovꓸcourses «ИИ-агенты и профессиональная разработка на Python» Алексей Жиряков покажет вживую, почему ИИ-код ломается в реальных проектах и как это исправлять.
Алексей — исполнительный директор в Сбере, занимается развитием генеративного ИИ, а до этого более 15 лет работал в backend-разработке и руководил инженерными командами.
Будет живое демо поверх готового репозитория: как настроить процесс, получить более чистый типизированный код и использовать продакшен-подход вроде связки «дешевая модель пишет — дорогая ревьюит», которая помогает снижать стоимость генерации.
Присоединяйтесь по ссылке, а после регистрации вы получите гайд «Почему ваш ИИ пишет не то: LLM против ИИ-агента»: https://clc.to/erid_2W5zFGkYPEH
Реклама. ООО «КАРПОВ КУРСЫ». ИНН 7811764627. erid: 2W5zFGkYPEH
Задача: 934. Shortest Bridge
Сложность: medium
Вам дана двоичная матричная сетка n x n, где 1 обозначает сушу, а 0 - воду. Остров - это 4-направленно связанная группа из 1, не соединенная ни с одной другой 1. В сетке ровно два острова. Вы можете поменять 0 на 1, чтобы соединить два острова в один. Верните наименьшее количество 0, которое нужно перевернуть, чтобы соединить два острова.
Пример:
👨💻 Алгоритм:
1⃣Найти все клетки, принадлежащие первому острову, используя DFS/BFS, и добавить их в очередь для последующего расширения.
2⃣Использовать BFS для расширения из каждой клетки первого острова, чтобы найти кратчайший путь к клетке второго острова.
3⃣Вернуть длину кратчайшего пути.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: medium
Вам дана двоичная матричная сетка n x n, где 1 обозначает сушу, а 0 - воду. Остров - это 4-направленно связанная группа из 1, не соединенная ни с одной другой 1. В сетке ровно два острова. Вы можете поменять 0 на 1, чтобы соединить два острова в один. Верните наименьшее количество 0, которое нужно перевернуть, чтобы соединить два острова.
Пример:
Input: grid = [[0,1],[1,0]]
Output: 1
👨💻 Алгоритм:
1⃣Найти все клетки, принадлежащие первому острову, используя DFS/BFS, и добавить их в очередь для последующего расширения.
2⃣Использовать BFS для расширения из каждой клетки первого острова, чтобы найти кратчайший путь к клетке второго острова.
3⃣Вернуть длину кратчайшего пути.
😎 Решение:
from collections import deque
def shortestBridge(grid):
n = len(grid)
def neighbors(x, y):
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
if 0 <= x + dx < n and 0 <= y + dy < n:
yield x + dx, y + dy
def bfs(queue):
visited = set(queue)
steps = 0
while queue:
new_queue = []
for x, y in queue:
for nx, ny in neighbors(x, y):
if (nx, ny) not in visited:
if grid[nx][ny] == 1:
return steps
visited.add((nx, ny))
new_queue.append((nx, ny))
queue = new_queue
steps += 1
def find_first_island():
for i in range(n):
for j in range(n):
if grid[i][j] == 1:
queue = deque([(i, j)])
grid[i][j] = -1
island = [(i, j)]
while queue:
x, y = queue.popleft()
for nx, ny in neighbors(x, y):
if grid[nx][ny] == 1:
grid[nx][ny] = -1
queue.append((nx, ny))
island.append((nx, ny))
return island
island = find_first_island()
return bfs(island)
Ставь 👍 и забирай 📚 Базу знаний
Задача: 1099. Two Sum Less Than K
Сложность: easy
Дан массив целых чисел nums и целое число k. Верните максимальную сумму, такую что существуют i < j, при которых nums[i] + nums[j] = sum и sum < k. Если не существует таких i и j, удовлетворяющих этому условию, верните -1.
Пример:
👨💻 Алгоритм:
1⃣Отсортируйте массив.
2⃣Установите указатели: левый на начало массива, правый на конец.
3⃣Пока левый указатель меньше правого:
Если сумма элементов по указателям меньше k, обновите максимальную сумму и сдвиньте левый указатель вправо.
Иначе сдвиньте правый указатель влево.
Верните максимальную сумму.
😎 Решение:
Ставь 👍 и забирай 📚 Базу знаний
Сложность: easy
Дан массив целых чисел nums и целое число k. Верните максимальную сумму, такую что существуют i < j, при которых nums[i] + nums[j] = sum и sum < k. Если не существует таких i и j, удовлетворяющих этому условию, верните -1.
Пример:
Input: nums = [34,23,1,24,75,33,54,8], k = 60
Output: 58
Explanation: We can use 34 and 24 to sum 58 which is less than 60.
👨💻 Алгоритм:
1⃣Отсортируйте массив.
2⃣Установите указатели: левый на начало массива, правый на конец.
3⃣Пока левый указатель меньше правого:
Если сумма элементов по указателям меньше k, обновите максимальную сумму и сдвиньте левый указатель вправо.
Иначе сдвиньте правый указатель влево.
Верните максимальную сумму.
😎 Решение:
class Solution:
def twoSumLessThanK(self, nums, k):
answer = -1
count = [0] * 1001
for num in nums:
count[num] += 1
lo, hi = 1, 1000
while lo <= hi:
if lo + hi >= k or count[hi] == 0:
hi -= 1
else:
if count[lo] > (0 if lo < hi else 1):
answer = max(answer, lo + hi)
lo += 1
return answer
Ставь 👍 и забирай 📚 Базу знаний