Максим Фатин | про алгосы
3.05K subscribers
82 photos
4 videos
75 links
Канал для тех, кто хочет освоить алгоритмы и структуры данных
Download Telegram
Задачка прямо из Озона в ленту

День знаний — значит нужно что-то умное написать

В общем

В ОЗОНЕ встречается задачка на разворот числа

Есть, скажем, число 123 — нужно получить 321

Топ-1 ред флаг: преобразовать в строку, развернуть, преобразовать в число

NO! NO! NO!

Больше на собес после такого могут не позвать (шучу)

В общем, нужен другой способ и он есть!

Скажем, есть у нас n = 123 — давай посмотрим по шагам, как его можно развернуть:

x = 0
n = 123

x = x * 10 + n % 10 = 0 + 3 = 3
n = n // 10 = 12

x = x * 10 + n % 10 = 30 + 2 = 32
n = n // 10 = 1

x = x * 10 + n % 10 = 320 + 1 = 321
n = n // 10 = 0


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

Задача решена?

ХРЕНОС ДВА

В условии есть такая шляпа: если при этом происходит переполнение, функция должна вернуть 0.

Чтобы это сделать, нужно при формировании обратного числа всё время делать проверку на переполнение

Это уже неочевидная штука, но в итоге получится такое решение:


from typing import *

def reverse_num(n: int) -> int:
result = 0
if n < 0:
return -reverse_num(-n)

max_int = 2 ** 31 - 1
while n > 0:
# проверка на переполнение
if result > max_int // 10:
return 0
result = result * 10 + n % 10
n //= 10
return result


Именно if result > max_int // 10: и помогает решить проблему и детектить переполнение

И это единственный способ, потому что int64 и длинную арифметику тебе тут использовать не разрешат

В противном случае могут записать как –1 балл

Решить можно самому на algocode.io:
https://algocode.io/courses/algo-big-tech/problem/reverse-num

Или на LeetCode:
https://leetcode.com/problems/reverse-integer/description/

И кайфового тебе дня и больших оферов! ✌️
❤‍🔥28🌭10
Как я готовил своего кореша в Яндекс

В общем, примерно полгода назад кореш попросил натаскать его по алгосам

Я такой — да без проблем, давай для начала устроим мок

Мок — это тот же собес, но не настоящий, а в кальянной 😂

В общем, дал ему для разминки такую задачу:

Есть массив и число target — нужно вернуть индексы позиций двух элементов, которые дают в сумме target

Мой кореш: «Да ты за лоха меня держишь? Я прекрасно знаю задачу two sum

А я, на секундочку, даже алгосов не знаю нормально»

Я: «Ну так реши раз просто»

Кореш: «Ну хеш-таблицу создаем, где ключ — элемент, а индекс — его позиция. По времени O(n) и по памяти тоже»

Я: «Не-а, по памяти не оптимально»

И тут до кореша доходит, что что-то тут не так

Я подсказываю ему, что решить задачу в текущей постановке нереально и нужно задавать дополнительные вопросы, чтобы понять, что делать

Хорошим вопросом был:

— А массив отсортирован?
Ответ: да.

Он такой — ну всё понятно, тогда ставим указатели на начало и конец, и если сумма = target, возвращаем индексы. В противном случае двигаем левый указатель если сумма текущих элементов меньше target и правый если больше. По времени O(n), по памяти O(1)

Я: «Не, кое-что не учли, и в некоторых случаях будет неправильный ответ»

Полыхать у него стало знатно 😂

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

🔥 ← мой кореш. Степень прожарки: medium rare.

Я решил добить до well done и сказал, что он не учитывает ещё возможное переполнение типов, а хотелось бы выбрасывать исключение на нём.

И в итоге получил полную прожарку кореша по алгосам.

Это я к чему:

Умение задавать вопросы — очень крутой навык, и некоторые задачи имеют много решений, а вопросы помогают понять, какое из них брать

И не все интервьюеры будут давать однозначное условие

Есть такие типы вопросов:

1) Ограничения
- какой длины массив максимум
- а сумма может давать переполнение типа
- какое максимальное/минимальное значение элементов в массиве
- а массив отсортирован
- и т. д.

2) Валидность данных
- могу ли я рассчитывать на ограничения или нужно их валидировать и выбрасывать исключение

3) Уточнить значение слов
- что такое палиндром
- что такое ось симметрии
- и т. д.

И ещё несколько типов, но самые важные я перечислил

Как правило, кандидаты с начальным уровнем алгоритмов задают вопросы:
- только для уточнения значения слов
- и для уточнения тесткейсов (почему в примере ответ XYZ)

А опытные кандидаты наоборот:
- задают вопросы только про ограничения
- и про валидность данных

Потому что значения слов они давно поняли, и у них в голове есть несколько решений

А вопросы про ограничения они используют, чтобы выбрать лучшее из всех вариантов и написать только его

Ну и бахни 🌭, если нашёл для себя в посте новые мысли и кайфанул
🌭87❤‍🔥5🤣2
Разваливаем собес Яндекса

Попалась задачка:

Дан массив отрезков segments, где segments[i] = [start, end] — бронирование комнаты для переговоров.
Нужно вернуть минимальное число комнат, чтобы все переговоры могли пройти.

Пример:

Ввод: [[2, 5], [1, 3]]
Вывод: 2


БАЗА? БАЗА!

---

Решение — метод точек

Суть в том, что каждый отрезок переводим в точки:

[2, 5] → [2, +1], [5, -1]
[1, 3] → [1, +1], [3, -1]


-1 означает конец отрезка, а +1 начало


Итого: [[2, +1], [5, -1], [1, +1], [3, -1]]


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


[[1, +1], [2, +1], [3, -1], [5, -1]]


ЮХУ! Финешь близок

Дальше — простой цикл: суммируем +1/-1 и ищем максимум.
Это и будет минимальное количество переговорных.

------

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

-------

Если что-то не понял, это нормально!

Тема не самая простая, а вот и решение для наглядности, которое ожидает интервьюер


from typing import List

def count_meeting_rooms(segments: List[List[int]]) -> int:
points = []
for start, end in segments:
points.append([start, +1]) # начало — нужна комната
points.append([end, -1]) # конец — комната освободилась

# при равенстве точек: сначала освобождаем комнату, потом занимаем
points.sort()

max_rooms = 0
curr_rooms = 0
for _, delta in points:
curr_rooms += delta
max_rooms = max(max_rooms, curr_rooms)
return max_rooms


А решить самому можно на algocode.io:
https://algocode.io/courses/algo-big-tech/problem/meeting-rooms

Или leetcode
https://leetcode.com/problems/meeting-rooms-ii/description/ (Premium)

Важный момент! Если у нас отрезок [[1, 3],[3, 4]] то ответ будет 1 (сначала комната освобождается, потом занимается).

НО!

Интервьюер может на раз два поменять условие (чтобы комната сначала занималась и только потом освобождалась) и ответ уже будет 2

Это регулируется сортировкой

Чтобы добиться порядка [1, +1], [3,+1], [3,-1], [4, -1] можно сортировать так:


points.sort(key=lambda x: (x[0], -x[1]))


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

Запомни только это и на собесе не будет ступора и быстро поймешь что делать!
🌭17❤‍🔥5
Не могу запомнить алго-задачу... Я тупой?

Когда я начинал учить алгосы и тупил на новой задаче всегда расстраивался

Что я делаю не так?

Почему не могу решить быстро?

И так хотелось бросить, что капец

НО

На стажировку в Яндекс хотелось сильнее 😂

В итоге я понял такую штуку: если я решаю задачку на какую-то идею и просто иду дальше, то потом очень низкий шанс, что я её решу снова

Но если решить хотя бы одну похожую задачу или просто тупо решить через время эту же, то результаты кратно круче

- Во-первых, лучше запоминается идея решения
- В новых задачах начинают виднеться уже изученные подходы

И наконец-то я начал видеть результат от изучения алгосов

В общем, максимально советую завести себе RETRY LIST (мне он помог)

RETRY LIST — это список ключевых задач лично для тебя, которые научили новому подходу, показали новую идею или просто важная задача, но никак не запомнишь

Если возвращаться к этим задачкам (их должно быть 15-20 не больше) то сможешь держать себя в форме

И не жди мега быстрого результата

Мне в своё время пришлось перерешивать все задачи по 2 раза и только потом открывался "третий глаз"

В общем, главное не останавливайся! Ты красавчик и всё сможешь!
❤‍🔥32🌭12🤣3
Вот такая задачка попалась мне в VK

АРЯЯЯЯ, ВОТ ЭТО ЗАДАЧКА, ВОТ ЭТО Я ПОНИМАЮ

Дан список возрастов и нужно выполнять запросы вида — сколько человек с возрастом от 2 до 100 лет, потом от -1000 до 100 000 и так далее


Да, столько не живут и возраста ограничены от 0 до 140 лет, но вот запросики могут быть в любом диапазоне

Прикол в том, что в ВК была 1 задача на 1 час

Но для нее так же писали тестики и т д, да и в целом интервью глубже получилось, потому что решали одну задачку и обговаривали все нюансы

Чтобы решить ее оптимально нужно знать:

- технику подсчета
- префиксные суммы

(префиксные суммы ) Те самые, что за O(1) помогают находить сумму на отрезке

Тут собственно точно такая же идея — заводим массив count на 141 элемент

count[i] — число людей с таким возрастом

А потом самое интересное: нужно построить префиксные суммы по возрастам

И Я ЗУБ ДАЮ, что многие на этом валятся и получают не оптимальное решение


# Подсчитываем количество людей по каждому возрасту
freq = [0] * 141
for age in ages:
freq[age] += 1

# Строим префиксную сумму по возрастам
px = [0] * 142
count = 0
for i in range(1, 142):
count += freq[i - 1]
px[i] = count

result = []
# Обработка запросов
....


Ну и остается аккуратно написать обработку запросов

Итого получаем O(1) по времени и памяти на запрос и O(n) по времени и памяти на моменте инициализации

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

Если бы запрос на статистику возрастов был 1, то конечно все это не имеет смысла

Поэтому важно общаться с интервьюером

А меня позвали в VK, но я отказался)

А порешать задачку можно тут:
https://algocode.io/courses/algo-big-tech/problem/age-statistics

(На leetcode не нашел аналога)

+ там же есть все темы чтобы научиться самому решать такие задачи

И больших тебе офферов!
🌭23❤‍🔥10
Вчера гоняли Go-шной командой в ресторан)

В общем, собрал 5 сильных ребят по гошке, и мы по выходным решаем задачки с собесов разных компаний

Дорешали все задачи с Яндекс Advanced Code и решили встретиться вживую — поехали в рестик познакомиться лично

Вообще кайфно получилось: и задачки порешали, и познакомились — всё в одном флаконе

Хочу собрать ещё одну группу единомышленников по алгосам

Если у тебя крутая экспертиза в алгоритмах и хочется потусоваться с единомышленниками — пиши в ЛС
@fatinmaks

- расскажу подробно, как всё устроено
- даём всем ребятам бесплатный доступ к algocode.io
- для разнообразия иногда выбираемся в рестораны и т. д. для личного знакомства

Кому подойдёт:
- уже есть экспертиза в алгоритмах
- есть желание и возможность раз в неделю разбирать задачи c собесов
- есть коммерческий опыт

В общем, если есть кайф — пиши 😉
https://t.me/fatinmaks
🌭15❤‍🔥3
Алгоритмы нужны не всем!

В целом к алгоритмам есть много вопросов:
- кому их учить
- как глубоко учить
- какой профит от этого
- ...

И чтобы ответить на вопрос «а надо ли оно мне» — давай поговорим честно.

Я прохожу собес на джуна, мне нужны алгосы?

— Спорно... Да, в вакансиях о них пишут, но по большей части они нужны только для стажировок в BigTech (Яндекс, Авито, Т-Банк и т. д.).
Я бы сказал, что для обычных вакансий достаточно очень базового уровня.
А вот для стажировок в BigTech нужны знания на серьёзном, олимпиадном уровне.

Я прохожу собес на мидла, мне нужны алгосы?

Уххх, брат! Ты прям в точку!
Вот как раз тебе алгоритмы могут дать самый большой карьерный буст!

1) Тебе открывается лёгкая дорога в BigTech — ведь алго-собес намного проще, чем контекст на стажёра
2) Подготовка к собеседованию в BigTech по алгосам занимает 2–3 месяца при плотной работе. Обычно порядка 50–60 задач достаточно, чтобы уверенно себя показывать
3) Можно закрыть гештальт и спокойно откликаться на большее число вакансий

Я прохожу собес на синьора, мне нужны алгосы?

Нуууу... ХЗ, ХЗ, ХЗ
Только если хочешь в BigTech. А так, лучше прокачивать навыки проектирования или менеджерские — с этого будет больше выхлопа

А так, у тебя скорее всего уже есть некоторая бицуха в алгосах

---

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

И если хочешь порешать задачки конкретных компаний или узнать инсайды по собесам — залетай в сообщество algocode.io

Только за последний месяц у нас +7 ребят устроились в Яндекс :)
🌭15❤‍🔥9
Спрашиваю кандидата: "Когда можно применять бинарный поиск?"

Ответ: когда массив отсортирован



Ну все, приехали как говорится :)


После такого ответа люблю спросить такую задачку:

Дано число x и нужно найти его корень без деления и встроенных функций в ЯП

И тут как правило кандидат садится на мель...


А задачка то решается тоже через бинарный поиск

Всего есть 3 фазы в бин. поиске

1) определить левую и правую границу между которыми ищем - допустимый диапазон для ответа

В данной задаче:

L = 0
R = x + 1

2) Определить функцию good, которая скажет двигать левый указатель для смещения диапазона или правый


ВОТ ЭТО САМЫЙ СЛОЖНЫЙ МОМЕНТ!

Объясняю на примере

вот есть число 4

И есть ряд чисел от 0 до 5 - ответ на вопрос какой корень из 4 точно лежит в этом диапазоне


0 1 2 3 4 5


Теперь давай отметим все элементы которые если возвести в квадрат получится <= 4 и будем считать их хорошими (G - good)

А все остальные (B - bad) плохими


0 1 2 | 3 4 5
G G G | F F F


Видно, что последовательность разделилась так: сначала все хорошие, а потом все плохие


И ЕСЛИ МОЖЕМ ПРИДУМАТЬ ТАКУЮ ФУНКЦИЮ

Которая разделит все последовательности во всех случаях сначала на хорошие элементы а потом на плохие

ТО ТОЛЬКО ТОГДА МОЖНО БИН ПОИСК ДЕЛАТЬ

В нашем случае функция good будет:


m * m <= x


Где m - текущее число (от 0 до x + 1)

3) Просто написать базовую болванку подставив туда значения L и R и функцию good


from typing import *

def find_sqrt(x: int) -> int:
# Note: работаем именно с целыми числами
# если работать с не целыми, то получим неточный ответ
# из-за накапливающейся неточности во float
l, r = 0, x + 1
while r - l > 1:
m = (l + r) // 2
if m * m <= x: # Функция good
l = m
else:
r = m
return l


Вообще, в хорошем бинарном поиске меняются только 3 строки:

1) значение L стартовое
2) значение R стартовое
3) функция good

Мало того что подход очень универсальный так и в нем понятно что в результате бинарного поиска

L - всегда смотрим на последний хороший элемент

R - на первый плохой


L R
0 1 2 | 3 4 5
G G G | F F F


И очень легко возвращать ответ с полным пониманием что такое L и R в результате бин. поиска

Более глубоко об этом рассказывал в видосе: https://www.youtube.com/watch?v=p-9zskDoaUE

До сих пор ору с этого видоса. Я там капец робот 😂😂😂
По контенту нормас)

-----------

А когда встретимся на собесе я обязательно спрошу тебя: а когда бинарный поиск можем использовать?

-----------

А решить задачку на algocode.io:
https://algocode.io/courses/algo-big-tech/problem/search-sqrt

Или leetcode:
https://leetcode.com/problems/sqrtx/description/

В общем, бин поиск это не только про массивы и применять его можно для чисел и даже для не отсортированных массивов. Есть даже задачка "Поиск в неотсортированном массиве" - решается тоже через бин. поиск
🌭21🤣1
Когда только начинал работать в Huawei познакомился с Лерой

Победитель ICPC


Мамма мия - победитель в олимпиадной проге - просто МАШИНА

Мне стало интересно как ее нанимали и какие задачки давали на входе

Оказалось, одной из задач было это:

"Дано число n Нужно вернуть true, если n является степенью двух, иначе false"

Честно, я ждал большего...

Ну там деревья крутануть пару раз...

Графы, сложные задачи на DP и все такое

САМОЕ ИНТЕРСНОЕ, что задачку на проверку степени двойки, котрая решается в 1 строчку

from typing import *

def is_power_of_two(n: int) -> bool:
return n > 0 and (n & (n - 1) == 0)


Лера забыла как решать

Ей было и смешно и стыдно, так как она знала это решение, но вот чет заклинило...

В итоге решила самым простым способом через деление и ее взяли

Я это к чему

На собесе бывает всякое и решить задачку хоть как-то лучше, чем не решить ничего

А когда пообщался с олимпиадниками, то понял, что им дает точно такие же задачи что и всем остальным

Интервьюеры то не олимпиадники по большей части 😂
🌭22❤‍🔥10
Quick sort повержен!

Закончил сценарий quick sort для ролика по сортировкам

Коротенечко пробежимся по основным подходам

В quick sort есть два стула:
- 2-way quick sort
- 3-way quick sort

2-way — делим массив на две части и сортируем каждую

3-way — делим на три части, но сортируем только две 😂

На картинке все наглядно видно

3-way спасает, когда в массиве куча повторяющихся элементов — не гоняем их туда-сюда по сто раз

НО ЭТО ТОЛЬКО БАЗА

В ролике копнем глубже: от учебной реализации до in-place quick sort с tailrec подходом и гарантией глубины рекурсии в log(n) + пооптимизируем сортировку мелких массивов

А еще в ролике будут:
- insertion sort
- selection sort
- count sort
- merge sort
- heap sort

Первые две — чисто разминка, а дальше пойдет настоящее мясо

Мой монтажер уже тихо плачет от количества анимаций, так что накидаем лойсов и поддержим его 😎

P.S. каждый лойс ускоряет выход ролика. Не байт, реально быстрее делаем)
❤‍🔥91🌭22
Подготовься к Go-собесам!

Новый курс для участников сообщества algocode.io

"Подготовься к Go-собесам"

Что внутри:

- 25+ задач на конкурентность — от fan-in/fan-out до свежих задач из секции Advanced Code в Яндексе

- 40+ задач всего, и к каждой есть эталонное решение — именно такое, какое ждёт интервьюер

- ботановская теория — чтобы наконец разобраться, что такое этот ваш GMP

- чат, где можно задать любые вопросы по курсу

---

Если есть кайф — залетай:
https://algocode.io/community

На всякий случай напомню: в подписке доступ не только к Go-курсу, но и к:
- Алгоритмам и структурам данных
- System Design


Так что гошнику можно подготовиться от и до

UPD: а скоро в подписке будет еще курсец по SQL для собесов
❤‍🔥10🌭7
Интервьюер жестко докопался к Big O

В общем, зашел тут ко мне кореш


Максон, был на собесе, но чет душить интервьюер стал

Я замялся с Big O маленько, а он накинулся и не давал писать код, пока не оценю...


Тут все просто: друган дал слабину там, где ее показывать нельзя

В тюрьме нельзя ронять мыло, а в алгоритмах — ошибаться в Big O

В целом, ошибаться можно

НО!

Когда кандидат оценивает в Big O память как O(n*n), а время O(n), то и у меня как у интервьюера возникает капец много вопросов

Простое правило: оценка по памяти НЕ МОЖЕТ ПРЕВЫШАТЬ ВРЕМЯ
Ведь аллокация той же самой памяти требует времени


После этого хочется понять — насколько глубоко кандидат реально разбирается

Вот и полетели другану дополнительные вопросы

---

В целом, редко встречаются оценки кроме как:
- O(1)
- O(n)
- O(n*log(n))
- O(n*n)
- O(n^n)

И есть +- понятные правила к каждой оценке

Например, для оценки времени:

- O(n*log(n)) — если используем встроенную сортировку и это самая затратная операция
- O(n) — один или несколько раз пробежаться по массиву
- O(n*n) — вложенный цикл в цикл (не путать с плавающим окном), в общем перебор всех пар в массиве
- O(1) — в оценке по времени почти никогда не используется
- O(n^n) — это полный перебор
- O(log(n)) - бинарный поиск как правило

Если говорить про частотность оценок времени, то я бы сказал так:
- O(n)
- O(n*log(n))
- O(n*n)
- O(n^n)
- O(log(n))
- O(1)

Это обусловлено частотностью разных тем на собесах

Например, сейчас в тренде задачки на массивы, указатели, хеш-таблицы — а это всё как правило O(n)

Сортировка бывает, но не так часто — O(n*log(n)

А по объему памяти обычно это:
- O(1)
- O(n)
- O(log(n))

Остальные оценки по памяти встречаются редко, а различить O(1) и O(n) несложно.
O(log(n)) встречается в сортировках и при рекурсивных обходах сбалансированных деревьев - тут не запутаешься тоже

В общем, тут я раскидал все основные аспекты, чтобы ты не запутался и с кайфом решал алгосы!
🌭34❤‍🔥11
Channel name was changed to «Максим Фатин | про алгосы»
Fit-собес — это самый главный этап во всех BigTech.

Тот самый собес, к которому рекрутер говорит "не готовься", но который на самом деле определяет:

- твой грейд
- ЗП
- команду...

Давай по порядку. Есть такие секции собеседований в BigTech:
- Скрининг (иногда скипают) — около 30 минут
- Платформа (проверяют знание языка) — 60 минут
- Алгоритмы — 60 минут
- System Design (для senior)
- Fit-собес

Fit-собес — это финальное интервью с твоим будущим руководителем, который как раз принимает финальное решение: интересно ли ему брать тебя в команду или нет.

а, да — именно Fit-собес, а не технические.
Если ты плохо прошёл технику — это твой ограничитель,
а если хорошо — это ещё не гарант Senior-грейда.

Живой пример — Авито.
Полно ребят, которые прошли все секции на Senior,
но в итоге получили Middle+, потому что не готовились к Fit-собесу...

На fit задают такие вопросы, как:
- Расскажи о себе (в профессиональном контексте)
- Расскажи о самой сложной технической задаче
- Как устроены процессы в команде?
- Как ты решаешь задачи?
- ...

Вопросы могут звучать странно, особенно если ты не понимаешь, на что они нацелены.

Пример хорошего ответа на вопрос "Расскажи о себе":

"Сейчас работаю в компании XYZ — она занимается B2B-решениями в аналитике и предоставляет SaaS-продукты.
Наша команда из шести человек разрабатывает AB-платформу для проведения A/B-тестов внутри всей компании.
Я занимаю роль Feature Lead-а и отвечаю за функциональность двух сервисов.

Первый — админка. Её основные пользователи — аналитики. Главная сложность — поддержание eventual consistency модели с соседними сервисами XYZ и ZYC.

Второй — сплитовалка, которая занимается распределением трафика. Здесь основной фокус — на performance и оптимизации.

Хочу рассказать об интересной челендж-задаче, которую решал для этого сервиса: ..."

Что здесь хорошо:
1. Кратко обозначено, чем занимается компания
2. Чётко описаны команда, роль и зона ответственности
3. Есть контекст по сервисам и взаимодействию с другими частями системы

Рассказывание занимает буквально 30 секунд, но уже создаёт прозрачное понимание, чем ты занимаешься.

Чем выше грейд собеседующего — тем больше он ценит точность формулировок. Поэтому стоит подготовиться заранее.

А теперь мега-фишка!

Найм — это всегда про доверие.
Если лид верит, что ты справишься с задачами — он готов выбивать тебе лучшие условия.
Если нет — то нет.


И вызвать это доверие очень просто:

- Подготовь структурированный рассказ
- Сделай презентацию к своему рассказу (так почти никто не делает!)
- Вместо вопросов вроде "А какая у вас версия Python?" спроси:
— какие планы на квартал или год
— какие ожидания от тебя как от кандидата
— каков основной фокус продукта

Так ты покажешь, что не просто технически подкован, но и умеешь принимать продуктовые решения.

Тех, кто может молча писать код, — пруд пруди.
А вот твоё конкурентное преимущество в 2025 году — это развитые soft skills.
Всё, что я перечислил выше, — это практические навыки, которые выделяют тебя на фоне остальных и дают стабильность даже в турбулентные времена.

Для ребят из сообщества algocode.io я уже провёл три эфира (суммарно более 6 часов), где детально разобрали все на реальных примерах + есть отдельно по Авито.

Если ты уже в сообществе — обязательно посмотри запись:


"Готов к BigTech"
https://t.me/c/2290576342/110

"Матрица компетенций из разбора"
https://t.me/c/2290576342/105

"А ты Senior?"
https://t.me/c/2290576342/99

"Как не упустить жирный офер в Авито"
https://t.me/c/2290576342/70

P.S. В разборах мы смотрели на middle+ инженеров и на их примере провели карьерный разбор

-----

Решил немного карьерой разнообразить канальчик - а то все про алгосы да про алгосы

Если хочешь дальше видеть посты про карьеру, то бахни 🌭
🌭67❤‍🔥3
Что не так с деревьями?

В чём вообще суть любой алгоритмической задачи? Найти оптимальное решение, которое будет эффективно работать на больших данных.

И это правило везде одно: решил не оптимально с точки зрения Big O — НА ВЫХОД!

Но почему-то это правило обошло деревья стороной...

Окей, окей — вот условие задачи прямо с собеса:

Дан корень правильного бинарного дерева поиска и число k. Нужно вернуть k-й наименьший элемент в дереве (отсчёт начинается с 1).

Бинарное дерево — значит, у каждой вершины не более двух детей.

Дерево поиска — значит, все элементы в левом поддереве меньше текущего, а в правом — больше.

Короче, вот пример дерева — и всё сразу станет ясно:


4
/ \
2 6
/ \ / \
1 3 5 7


Пусть k = 3. Тогда третий наименьший элемент — это 3, именно её и нужно вернуть по условию.

Чтобы решать задачи на деревья, нужно знать три обхода: preorder, inorder, postorder.
Они позволяют обойти все вершины дерева в определённом порядке.

Для примера выше:

preorder: 4, 2, 1, 3, 6, 5, 7
inorder: 1, 2, 3, 4, 5, 6, 7
postorder: 1, 3, 2, 5, 7, 6, 4


Заметил? inorder выдал отсортированный порядок — и это не совпадение!

Если дерево — правильное бинарное дерево поиска, то inorder всегда выдаёт отсортированную последовательность.

Реализация inorder-обхода:


from typing import *
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right

def traversal(node: Optional[TreeNode], result: List[int]) -> None:
if node is None:
return
traversal(node.left, result)
result.append(node.val)
traversal(node.right, result)

def inorder_traversal(root: Optional[TreeNode]) -> List[int]:
result = []
traversal(root, result)
return result


Простое решение задачи:
1. Запускаем inorder и получаем отсортированный список.
2. Возвращаем k-й элемент (с индексом k - 1).

Оценка: время — O(n), память — O(n).

Но! Такое решение на собеседовании часто не принимают. Слишком много дополнительной памяти — хочется оптимальнее.

Какое решение ждут: нужно прямо во время обхода считать, какой элемент мы посещаем, и если он k-й — вернуть его сразу, не сохраняя все значения вершин дерева.


from typing import *
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right

def smallest_bst_element(root: TreeNode, k: int) -> int:
def inorder(node: TreeNode) -> int:
if node is None:
return None
result = inorder(node.left)
if result is not None:
return result
nonlocal k
k -= 1
if k == 0:
return node.val
return inorder(node.right)
return inorder(root)


Оценка: время — O(n), память — O(n).

WTF? Почему такие же оценки, если вроде оптимизировали?

Пусть k = 1, а дерево выглядит вот так — «бамбук» с уклоном влево:

4
/
3
/
2
/
1


Видишь? Нам всё равно придётся спуститься в самый низ, чтобы достать единицу — самый минимальный элемент.

А память откуда O(n)? Из-за рекурсии, брат! Каждый рекурсивный вызов занимает место в стеке.

В худшем случае это O(h), где h — высота дерева, а если дерево вытянутое, то просто h = n.

P.S. продолжение через минуты
🌭5🍓2
Что не так с деревьями?

🤙🤙🤙 Продолжение поста выше

📌 Много букв, но ты справишься!

---------

А теперь, когда ты всё это прочитал, самый прикол!

Это решение всё ещё не самое оптимальное. Дело в том, что есть обход Морриса (Morris Traversal). Такой обход не использует рекурсию и стек, поэтому решение получается O(n) по времени и O(1) по памяти.

С ним решение выглядит так:


from typing import *
from algocodelib import TreeNode

def smallest_bst_element(root: TreeNode, k: int) -> int:
curr = root
while curr:
if curr.left is None:
# посещаем узел
k -= 1
if k == 0:
return curr.val
curr = curr.right
else:
# ищем inorder-предшественника (правыйmost узел в левом поддереве)
pred = curr.left
while pred.right and pred.right is not curr:
pred = pred.right
if pred.right is None:
# создаём временную ссылку
pred.right = curr
curr = curr.left
else:
# убираем ссылку и посещаем узел
pred.right = None
k -= 1
if k == 0:
return curr.val
curr = curr.right
return -1 # если k больше, чем количество узлов


Юху! Решили оптимально!

Но вот интервьюер вряд ли такое оценит...

Во-первых, есть риск, что он не знает про такие оптимальные подходы и просто посчитает решение некорректным
Во-вторых — ну оно реально жёсткое, и легко накосячить на мелочах

В общем, рекурсия в деревьях для решения задачи — это база. Да, не оптимально по памяти в худшем случае, но это база!

Где такое возможно еще??? А вот почти нигде - деревья тут отличились. В остальных темах надо оптимально решать...

Всем достаточно рекурсивного обхода 🙂

P.S. Если встретимся на собесе и ты расскажешь про обход Морриса и напишешь без ошибок — вторую задачу не дам: сразу апрув

Бахни 🌭 если зашел формат лонгрида! Если наберем 80+ сосисонов, то буду чаще в таком формате посты делать
🌭105
А Озон-то не так прост!

Вообще, мало где дают задачки на системы счисления — так что Озон тут выделяется.


Недавно попалась вот такая задачка:

Дан номер колонки в Excel. Нужно назвать её порядковый номер.

Примеры:

A -> 1
B -> 2
...
Z -> 26
AA -> 27
AB -> 28


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

ord — это функция, которая возвращает ASCII-код символа.

Например:

ord('A') = 65
ord('B') = 66
...
ord('Z') = 90


Да, без этого можно обойтись, но это база, как говорится.

Таким образом, мы можем сопоставить каждой букве её номер:


'A' -> ord('A') - ord('A') + 1 = 1
'B' -> ord('B') - ord('A') + 1 = 2
...
'Z' -> ord('Z') - ord('A') + 1 = 26


Бинго!

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

Теперь можно воспринимать строку так:


'AB' → [1, 2] → 1 * 26 + 2 = 28
'ABCD' → [1, 2, 3, 4] → 1 * 26³ + 2 * 26² + 3 * 26 + 4


Откуда взялось 26?

У нас всего 26 различных символов. Если бы алфавит был только A B C, то умножали бы на 3...


Осталось только собрать всё вместе:


from typing import *

# Время: O(n)
# Память: O(1)
def int_from_excel_column(column: str) -> int:
result = 0
for ch in column:
val = ord(ch) - ord('A') + 1
result = result * 26 + val
return result


ВАЖНО!

Ожидают решение по памяти за O(1), так что составлять массив из чисел, а потом считать результат — не вариант (это было нужно только для объяснения).

В боевом решении всё должно быть оптимально.

Вообще, формула:

result = result * 26 + val

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

Решить задачку можно у нас на algocode.io как и другие задачи Озона:

https://algocode.io/courses/algo-big-tech/problem/int-from-excel-column

или на leetcode:
https://leetcode.com/problems/excel-sheet-column-title/description/
❤‍🔥21🌭7
Что спросить у СТО, чтобы тебя наняли на высокий грейд?

Проходя собесы, я начал 1.5 года назад активно общаться с СТО на финальной секции

Получается, уже не просто маслёнок...

Как правило, это серьёзные дяди — и разговорить их было не всегда просто

Я прям видел отвращение в лицах после вопросов:
- «А какая версия Go у вас в проектах?»
- «А есть компенсация обедов?»

Просто разрыв живота 99-го уровня — как вспомню своё общение с СТО полтора года назад...

Главное правило общения с лидом и СТО, которое я вынес, чтобы вопросы не вызывали отвращения:

Не спрашивай то, на что может ответить рекрутер или то, что уже написано в вакансии. Потом у рекрутера уточнишь, если тебе важно.

А теперь важно определить цель вопросов:

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

Например, для себя я понял:

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

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

- Хочу работать в богатой компании или там, где знаком с владельцем бизнеса. Всё просто: если компания уже богатая, значит, там дофига людей, с кем можно познакомиться и перенять опыт. Если мелкая — то я хочу вносить импакт на уровне всей компании, а для этого нужно общаться с собственником

И теперь у меня есть простой чеклист

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

И знаете что?

99% fit-собесов я просто скипаю, потому что я не подхожу команде или она мне...

У меня нет задачи нравиться всем. Я хочу самый пиздатый матч, который только возможен.

Чтобы компания, которая меня нанимала, заработала на мне Х10, а лучше — Х100


Потому что в таком случае и я без денег не останусь, и компании будет капец как выгодно

WIN-WIN

Я не хочу быть посредственным!
Просто не хочу.

Так что вот мои вопросы:

- Какие цели у юнита на год, и у команды, куда меня рассматриваете, в частности?

- Какую роль продукт оказывает на бизнес и является ли ключевым?

- Какие ожидания у бизнеса от продукта? На какие метрики смотрит бизнес?

- Чем отличаетесь от конкурентов / планируете отличаться и кто они?

- Какие направления развиваете: B2B/B2C/B2G, и какие по ним планы?

- Довольны ли вы сейчас работой команды, куда меня нанимают, или есть критические поинты для улучшения?

----

В общем, я отказался от вопросов про ЯП 😂

Ну мне реально стало не особо интересно. Больше хочется про продукт узнать — его экономику и важность.

Этот чеклист точно не для тех, кто ищет первую работу.

Но зато тот 1%, в который попадает матч, выкатывает очень приятные офферы на 600+ кэсов.

А какие вопросы на финалах задаёшь ты? Интересно будет глянуть комменты

P.S. экспериментирую с форматами постов так что бахни 🌭 если зашло
🌭88❤‍🔥6🍓2
Стартует запись на курс по графам!

Курс пройдет с 25 ноября по 9 декабря

- Программа из тем
- Про домашки
- Про проверку домашек
- Как попасть на курс
- ...
https://telegra.ph/Kurs-Grafy-s-0-do-PRO-11-05

Число мест для live-участия ограничего!

Для тех, кто решится на онлайн - советую подавать заявку как можно раньше,
потому что уже начали анализировать заявки

P.S. обязательно буду делиться с вами ключевыми инсайдами по ходу курса, чтобы все могли получить пользу
❤‍🔥3🌭2