Python | LeetCode
10.1K subscribers
157 photos
2 videos
1.07K links
Cайт easyoffer.ru
Реклама @easyoffer_adv
ВП @easyoffer_vp

Тесты t.me/+20tRfhrwPpM4NDQy
Вопросы собесов t.me/+cnJC0_ZeZ_I0OGY6
Вакансии t.me/+cXGKkrOY2-w3ZTky
Download Telegram
Задача: 113. Path Sum II
Сложность: Medium

Дан корень бинарного дерева и целое число targetSum. Верните все пути от корня до листа, где сумма значений узлов в пути равна targetSum. Каждый путь должен быть возвращён как список значений узлов, а не ссылок на узлы.

Путь от корня до листа — это путь, начинающийся от корня и заканчивающийся на любом листовом узле. Лист — это узел без детей.

Пример:
Input: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
Output: [[5,4,11,2],[5,8,4,5]]
Explanation: There are two paths whose sum equals targetSum:
5 + 4 + 11 + 2 = 22
5 + 8 + 4 + 5 = 22


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

1️⃣Определение функции recurseTree: Функция принимает текущий узел (node), оставшуюся сумму (remainingSum), которая необходима для продолжения поиска вниз по дереву, и список узлов (pathNodes), который содержит все узлы, встреченные до текущего момента на данной ветке.

2️⃣Проверка условий: На каждом шаге проверяется, равна ли оставшаяся сумма значению текущего узла. Если это так и текущий узел является листом, текущий путь (pathNodes) добавляется в итоговый список путей, который должен быть возвращен.

3️⃣Обработка всех ветвей: Учитывая, что значения узлов могут быть отрицательными, необходимо исследовать все ветви дерева до самых листьев, независимо от текущей суммы по пути.

😎 Решение:
class TreeNode:
def __init__(self, x: int) -> None:
self.val = x
self.left = None
self.right = None


class Solution:

def recurseTree(
self,
node: TreeNode,
remainingSum: int,
pathNodes: List[int],
pathsList: List[List[int]],
) -> None:

if not node:
return

pathNodes.append(node.val)

if remainingSum == node.val and not node.left and not node.right:
pathsList.append(list(pathNodes))
else:
self.recurseTree(
node.left, remainingSum - node.val, pathNodes, pathsList
)
self.recurseTree(
node.right, remainingSum - node.val, pathNodes, pathsList
)

pathNodes.pop()

def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
pathsList = []
self.recurseTree(root, sum, [], pathsList)
return pathsList


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 1469. Find All The Lonely Nodes
Сложность: easy

В бинарном дереве одиночный узел — это узел, который является единственным ребёнком своего родительского узла. Корень дерева не является одиночным, так как у него нет родительского узла.

Дано корневое значение бинарного дерева. Верните массив, содержащий значения всех одиночных узлов в дереве. Верните список в любом порядке.

Пример:
Input: root = [7,1,4,6,null,5,3,null,null,null,null,null,2]
Output: [6,2]
Explanation: Light blue nodes are lonely nodes.
Please remember that order doesn't matter, [2,6] is also an acceptable answer.


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

1⃣Определите рекурсивную функцию DFS, которая принимает корень дерева, булеву переменную isLonely и список одиночных узлов ans в качестве аргументов. Если корень равен NULL, завершите выполнение функции.

2⃣ Если isLonely равен true, добавьте значение корня в список ans. Рекурсивно обрабатывайте левого потомка корня, устанавливая флаг isLonely в true, если правый потомок равен NULL, и правого потомка, устанавливая флаг isLonely в true, если левый потомок равен NULL.

3⃣Вызовите DFS с корнем и false в качестве значения isLonely. Верните ans.

😎 Решение:
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right

class Solution:
def DFS(self, root, isLonely, ans):
if root is None:
return

if isLonely:
ans.append(root.val)

self.DFS(root.left, root.right is None, ans)
self.DFS(root.right, root.left is None, ans)

def getLonelyNodes(self, root):
ans = []
self.DFS(root, False, ans)
return ans


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

Предположим, у вас есть n целых чисел, пронумерованных от 1 до n. Перестановка этих n целых чисел perm (нумерация с 1) считается красивой, если для каждого i (1 <= i <= n) выполняется одно из следующих условий:
perm[i] делится на i.
i делится на perm[i].
Дано целое число n, верните количество красивых перестановок, которые вы можете создать.

Пример:
Input: n = 2
Output: 2
Explanation:
The first beautiful arrangement is [1,2]:
- perm[1] = 1 is divisible by i = 1
- perm[2] = 2 is divisible by i = 2
The second beautiful arrangement is [2,1]:
- perm[1] = 2 is divisible by i = 1
- i = 2 is divisible by perm[2] = 1


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

1⃣ Инициализация и подготовка массива:
Создайте массив чисел от 1 до N и инициализируйте счетчик красивых перестановок.
Создайте функцию для перестановки элементов массива.

2⃣ Рекурсивное создание перестановок и проверка условий:
Напишите рекурсивную функцию для создания всех возможных перестановок массива, начиная с текущей позиции l.
На каждом шаге перестановки проверяйте, удовлетворяет ли текущий элемент условиям делимости. Если условие выполняется, продолжайте создание перестановок рекурсивно для следующей позиции.

3⃣ Возврат результата:
В основной функции вызовите рекурсивную функцию с начальной позицией 0 и верните значение счетчика красивых перестановок.

😎 Решение:
class Solution:
def __init__(self):
self.count = 0

def countArrangement(self, N: int) -> int:
nums = list(range(1, N + 1))
self.permute(nums, 0)
return self.count

def permute(self, nums, l):
if l == len(nums):
self.count += 1
for i in range(l, len(nums)):
nums[i], nums[l] = nums[l], nums[i]
if nums[l] % (l + 1) == 0 or (l + 1) % nums[l] == 0:
self.permute(nums, l + 1)
nums[i], nums[l] = nums[l], nums[i]


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
📺 База 1000+ реальных собеседований

На программиста, тестировщика, аналитика, проджекта и другие IT профы.

Есть собесы от ведущих компаний: Сбер, Яндекс, ВТБ, Тинькофф, Озон, Wildberries и т.д.

🎯 Переходи по ссылке и присоединяйся к базе, чтобы прокачать свои шансы на успешное трудоустройство!
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 715. Range Module
Сложность: hard

Модуль Range - это модуль, который отслеживает диапазоны чисел. Создайте структуру данных для отслеживания диапазонов, представленных в виде полуоткрытых интервалов, и запросов к ним. Полуоткрытый интервал [left, right) обозначает все вещественные числа x, где left <= x < right. Реализуйте класс RangeModule: RangeModule() Инициализирует объект структуры данных. void addRange(int left, int right) Добавляет полуоткрытый интервал [left, right), отслеживая каждое вещественное число в этом интервале. Добавление интервала, который частично перекрывает отслеживаемые в данный момент числа, должно добавить все числа в интервале [left, right), которые еще не отслеживаются. boolean queryRange(int left, int right) Возвращает true, если каждое действительное число в интервале [left, right) отслеживается в данный момент, и false в противном случае. void removeRange(int left, int right) Прекращает отслеживание каждого действительного числа, отслеживаемого в данный момент в полуоткрытом интервале [left, right).

Пример:
Input: prices = [1,3,2,8,4,9], fee = 2
Output: 8


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

1⃣Инициализируйте класс RangeModule с пустым списком диапазонов.

2⃣Для метода addRange(left, right) добавьте новый диапазон, объединяя его с существующими перекрывающимися диапазонами. Для метода queryRange(left, right) проверьте, полностью ли данный диапазон содержится в отслеживаемых диапазонах.

3⃣Для метода removeRange(left, right) удалите указанный диапазон, разбивая существующие диапазоны на соответствующие части.

😎 Решение:
class RangeModule:

def __init__(self):
self.ranges = []

def addRange(self, left, right):
new_ranges = []
i = 0
while i < len(self.ranges) and self.ranges[i][1] < left:
new_ranges.append(self.ranges[i])
i += 1
while i < len(self.ranges) and self.ranges[i][0] <= right:
left = min(left, self.ranges[i][0])
right = max(right, self.ranges[i][1])
i += 1
new_ranges.append((left, right))
while i < len(self.ranges):
new_ranges.append(self.ranges[i])
i += 1
self.ranges = new_ranges

def queryRange(self, left, right):
for l, r in self.ranges:
if l <= left and right <= r:
return True
return False

def removeRange(self, left, right):
new_ranges = []
for l, r in self.ranges:
if l < left:
new_ranges.append((l, min(r, left)))
if right < r:
new_ranges.append((max(l, right), r))
self.ranges = new_ranges


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

Дан массив транзакций transactions, где transactions[i] = [fromi, toi, amounti] указывает на то, что человек с ID = fromi дал сумму amounti долларов человеку с ID = toi.

Верните минимальное количество транзакций, необходимых для урегулирования долгов.

Пример:
Input: transactions = [[0,1,10],[2,0,5]]
Output: 2


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

1⃣Создать хеш-таблицу для хранения чистого баланса каждого человека.

2⃣Собрать все ненулевые чистые балансы в массив balance_list.

3⃣Определить рекурсивную функцию dfs(cur) для очистки всех балансов в диапазоне balance_list[0 ~ cur]:
Игнорировать cur, если баланс уже равен 0. Пока balance_list[cur] = 0, переходить к следующему человеку, увеличивая cur на 1.
Если cur = n, вернуть 0.
В противном случае установить cost на большое значение, например, inf.
Пройтись по индексу nxt от cur + 1, если balance_list[nxt] * balance_list[cur] < 0,
Добавить баланс balance_list[cur] к balance_list[nxt]: balance_list[nxt] += balance_list[cur].
Рекурсивно вызвать dfs(cur + 1) как dfs(cur) = 1 + dfs(cur + 1).
Убрать ранее переданный баланс от cur: balance_list[nxt] -= balance_list[cur] (откат).
Повторить с шага 5 и отслеживать минимальное количество операций cost = min(cost, 1 + dfs(cur + 1)), найденных в итерации.
Вернуть cost, когда итерация завершена. Вернуть dfs(0).

😎 Решение:
class Solution:
def minTransfers(self, transactions: List[List[int]]) -> int:
from collections import defaultdict

credit_map = defaultdict(int)
for t in transactions:
credit_map[t[0]] += t[2]
credit_map[t[1]] -= t[2]

credit_list = [amount for amount in credit_map.values() if amount != 0]
n = len(credit_list)

def dfs(cur):
while cur < n and credit_list[cur] == 0:
cur += 1
if cur == n:
return 0
cost = float('inf')
for nxt in range(cur + 1, n):
if credit_list[nxt] * credit_list[cur] < 0:
credit_list[nxt] += credit_list[cur]
cost = min(cost, 1 + dfs(cur + 1))
credit_list[nxt] -= credit_list[cur]
return cost

return dfs(0)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Please open Telegram to view this post
VIEW IN TELEGRAM
Зарплата 207.000р у Middle-разработчика в Яндекс

«В день уходит несколько часов на созвоны, в остальное время закрываю задачки из спринта, редко перерабатываю. У компании топовый офис, но с коллективом как-то не заладилось. Радуюсь классному ДМС и стабильной зарплате» - middle разработчик из Яндекса.

Бигтех по-русски - канал с реальными зарплатами и историями IT-специалистов российского БигТеха. Там уже опубликованы рассказы программистов Альфа-банка, Сбера и Тинькофф 🤯

Читайте: @bigtech_russia
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача: 647. Palindromic Substrings
Сложность: medium

Если задана строка s, верните количество палиндромных подстрок в ней. Строка является палиндромом, если она читается так же, как задом наперед. Подстрока - это непрерывная последовательность символов в строке.

Пример:
Input: s = "abc"
Output: 3


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

1⃣Инициализируйте счетчик для подсчета палиндромных подстрок.

2⃣Для каждой позиции в строке используйте два метода расширения: один для палиндромов нечетной длины и один для палиндромов четной длины.

3⃣Расширяйте от центра, проверяя, является ли подстрока палиндромом, и увеличивайте счетчик, если условие выполняется.

😎 Решение:
def countSubstrings(s):
def expandAroundCenter(left, right):
count = 0
while left >= 0 and right < len(s) and s[left] == s[right]:
count += 1
left -= 1
right += 1
return count

total_count = 0
for i in range(len(s)):
total_count += expandAroundCenter(i, i) # For odd length palindromes
total_count += expandAroundCenter(i, i + 1) # For even length palindromes
return total_count


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

Вам дана строка s и массив строк-слов. Все строки-слова имеют одинаковую длину.

Объединенная строка - это строка, которая точно содержит все строки из любой перестановки слов, которые были объединены.

Например, если words = ["ab", "cd","ef"], то "abcdef", "abefcd", "cdabef", "cdefab", "efabcd" и "efcdab" являются связанными строками. "acdbef" не является объединенной строкой, потому что это не объединение какой-либо перестановки слов.

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

Пример:
  
Input: s = "barfoothefoobarman", words = ["foo","bar"]
Output: [0,9]


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

1️⃣Создаем словарь с подсчетом количества слов в words.

2️⃣Проходим по строке s, проверяя подстроки длины, равной len(words) * len(words[0]).

3️⃣Проверяем, содержит ли подстрока все слова из words в нужном количестве.

😎 Решение:
from collections import defaultdict  

class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
if not s or not words:
return []

word_count = defaultdict(int)
for word in words:
word_count[word] += 1

substr_len = len(words) * len(words[0])
word_len = len(words[0])
result = []

for i in range(len(s) - substr_len + 1):
seen = defaultdict(int)
for j in range(i, i + substr_len, word_len):
word = s[j:j+word_len]
if word in word_count:
seen[word] += 1
if seen[word] > word_count[word]:
break
else:
break
else:
result.append(i)

return result


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

Дан корень бинарного дерева. Верните то же дерево, в котором удалены все поддеревья (данного дерева), не содержащие 1.

Поддерево узла node - это сам узел node и все узлы, являющиеся потомками node.

Пример:
Input: root = [1,null,0,0,1]
Output: [1,null,0,null,1]
Explanation:
Only the red nodes satisfy the property "every subtree not containing a 1".
The diagram on the right represents the answer.


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

1⃣Используем функцию containsOne(node), которая сообщает, содержит ли поддерево в данном узле единицу, и обрезает все поддеревья, не содержащие единицу.

2⃣Например, если поддерево node.left не содержит единицу, то мы должны обрезать его через node.left = null.

3⃣Также нужно проверить родительский узел. Например, если дерево состоит из одного узла 0, то ответом будет пустое дерево.

😎 Решение:
class Solution:
def pruneTree(self, root):
def containsOne(node):
if not node:
return False

leftContainsOne = containsOne(node.left)
rightContainsOne = containsOne(node.right)

if not leftContainsOne:
node.left = None
if not rightContainsOne:
node.right = None

return node.val == 1 or leftContainsOne or rightContainsOne

return root if containsOne(root) else None


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