Petr
https://t.me/ctci_chat_ru/38942
Спасибо! А расскажи пожалуйста, как ты харды решал? Я только начинаю, у меня уходит пара часов как минимум допереть до решения самостоятельно. Это норм стратегия?
Порридж В Ко-ливинге
Порридж В Ко-ливинге
Спасибо! А расскажи пожалуйста, как ты харды решал? Я только начинаю, у меня уходит пара часов как минимум допереть до решения самостоятельно. Это норм стратегия?
Я половину задачек решал 2-3мя способами, где-то наилучшая сложность по памяти, где-то по скорости, где-то старался в 1-3 строчки решить (в Питоне это легко используя itertools). Я могу на одну задачу 1-2 часа тратить, иногда целый день, если интересно.
Порридж В Ко-ливинге
Часто ещё решения выкладывал в обсуждения. Старался чтобы код был красивый. Редко находили что можно сделать лучше и так прокачивался, но это надо делать на daily задачках
Alexey
Сегодня проходил собес в мете, попалась следующая задача Нужно было найти любой путь в гриде из левого верха до правого низа, где 1 - стенка, 0 - ячейка, по ктр можно ходить. В качестве ответа возвращать null, если пути не существует, иначе массив координат любого пути я решил через dfs рекурсивный, но интервьюер не принял решение, т.к. я сказал, что по памяти это O(n*m), где n - колво строк в гриде, m - колво столбцов в гриде. При этом по времени O(n*m) устроило Рассуждая вслух: - bfs не подошел, потому что для каждой позиции надо было хранить промежуточный путь, что по памяти было бы еще хуже - мб итеративный dfs со стеком был бы лучше по памяти? По намекам ощущение, что напрашивалось O(m+n) доп памяти Есть какие-нибудь предложения?
Порридж В Ко-ливинге
Сегодня проходил собес в мете, попалась следующая задача Нужно было найти любой путь в гриде из левого верха до правого низа, где 1 - стенка, 0 - ячейка, по ктр можно ходить. В качестве ответа возвращать null, если пути не существует, иначе массив координат любого пути я решил через dfs рекурсивный, но интервьюер не принял решение, т.к. я сказал, что по памяти это O(n*m), где n - колво строк в гриде, m - колво столбцов в гриде. При этом по времени O(n*m) устроило Рассуждая вслух: - bfs не подошел, потому что для каждой позиции надо было хранить промежуточный путь, что по памяти было бы еще хуже - мб итеративный dfs со стеком был бы лучше по памяти? По намекам ощущение, что напрашивалось O(m+n) доп памяти Есть какие-нибудь предложения?
Бред. У тебя может быть просто змейкой из края в край идти путь, и он уже будет N*M. Т.е. интервьюер сам не понял что захотел. Ответ минимум N*M.
Порридж В Ко-ливинге
Бектрекинг нормальный вариант, только не уверен, что память можно оценить как N + M
Я ж говорю, там уже из-за ответа ниже N*M не получится. Змейкой идёшь и всё
Alexey
На эту похоже https://leetcode.com/problems/shortest-path-in-binary-matrix/description/ ?
Похоже, но мне поиск не кратчайшего, а любого надо. А решение - не число, а массив. Это прям дает сильно отличие в решении, хотя набор подходов не отличается
Viktor
Похоже, но мне поиск не кратчайшего, а любого надо. А решение - не число, а массив. Это прям дает сильно отличие в решении, хотя набор подходов не отличается
Ну да, вот для пути я как раз и предлагаю бектрекинг, это то, что ты назвал «интерактивный dfs со стеком», видимо
igors
И повторно уже не идти
Порридж В Ко-ливинге
00000000000000000000000 1111111111111111111111111111110 00000000000000000000000 0111111111111111111111111111111 00000000000000000000000 1111111111111111111111111111110 00000000000000000000000 0111111111111111111111111111111 00000000000000000000000 Тут уже координат фигова туча
Порридж В Ко-ливинге
Я этот же пример привел, не убедило)))
Конченный интервьюер. Как это не переубедило? Я бы сразу после интервью написал бы рекрутёру, что чел под наркотой меня собесил, посмотрите реплей
Порридж В Ко-ливинге
Это ты ему показываешь на корову, а он просит сесть в неё, называя это Ламборгини и выжать 100 км/ч? Он же наркоман
Порридж В Ко-ливинге
Нормально так понанимали в Ковид челиков... Зато меня не взяли и куча талантливых. Не дай бог косты вырастут, акции должны расти!!!
Alexey
Ну там можно запоминать пути по которым ходил
Угу, я хранил глобальный стейт пути и добавлял перед рекурсивным вызовом, если не подходило, убирал координату из пути
igors
Ну что сказать
igors
Надо рекрутеру написать
Порридж В Ко-ливинге
Угу, я хранил глобальный стейт пути и добавлял перед рекурсивным вызовом, если не подходило, убирал координату из пути
Мне кажется это единственный метод. Может он не простой наркоман, а героиновый, и хотел чтобы ты сделал long long int и хранил в нём путь как в бинарном дереве?
Alexey
Короче я понял, я еще сомневался, что мб я упоролся, не вижу очевидное решение, но обсуждал уже людьми с 4 и пока лучше решение не нашел
Viktor
Угу, я хранил глобальный стейт пути и добавлял перед рекурсивным вызовом, если не подходило, убирал координату из пути
Просто если N + M, то это как будто у тебя есть жадный алгоритм для выбора куда двигаться, так что в пределе нет такого, что ты проверяешь все клетки
Viktor
Но его нет 😃
Alexey
Но его нет 😃
Ну вот да
Viktor
Надо рекрутеру написать
Написать, что совет литкодеров постановил выдать нормального собеседующего 🤣
Alexey
На первом собесе с easy и hard уже получил strong hire и уверен, что второй технический тоже strong hire. А тут меня мурижили 35 мин на одной задачи и не дали вторую. Я возмущен
igors
Мне кажется есть такая задачка gridTraveller когда надо тоже с левого верхнего в правый нижний дойти, двигаясь только вправо и вниз, вот там n+m. Кароче походу он сам запутался)))
Viktor
Надо короче как на кодфорсес, чтобы автор контеста после завершения показывал свои решения 😃
igors
Во-во
igors
А то знаю я любителей задавать вопросы ответы на которые они сами не знают)))
Alexey
Просто если N + M, то это как будто у тебя есть жадный алгоритм для выбора куда двигаться, так что в пределе нет такого, что ты проверяешь все клетки
Тут даже не то, что я не проверяю не все клетки, по времени ок все проверять, но вот в глубину dfs уходить не больше, чем пропорционально m+n - как-то неестественно, имея dfs, который идет до предельных значений, пока в тупик не уйдешь
Alexey
Только N, W, E, S
igors
А ну так эта та задачка
igors
Что я написал
igors
Там n+m
Alexey
А можешь сбросить описание задачи, если под рукой? (Или завтра)
Alexey
Я хочу разобраться с ней и понять, что имеется в виду
igors
Давай завтра
igors
Можно там даже дерево построить
Vitaly
Сегодня проходил собес в мете, попалась следующая задача Нужно было найти любой путь в гриде из левого верха до правого низа, где 1 - стенка, 0 - ячейка, по ктр можно ходить. В качестве ответа возвращать null, если пути не существует, иначе массив координат любого пути я решил через dfs рекурсивный, но интервьюер не принял решение, т.к. я сказал, что по памяти это O(n*m), где n - колво строк в гриде, m - колво столбцов в гриде. При этом по времени O(n*m) устроило Рассуждая вслух: - bfs не подошел, потому что для каждой позиции надо было хранить промежуточный путь, что по памяти было бы еще хуже - мб итеративный dfs со стеком был бы лучше по памяти? По намекам ощущение, что напрашивалось O(m+n) доп памяти Есть какие-нибудь предложения?
Эм... Но ведь dfs не будет по времени O(n*m) 😄 dfs перебирает все возможные траектории, пока не встретит нужную. Если нужной нет, то вообще все возможные и, кажется, их типа 3^(n+m), т.к. из каждой ячейки мы можем в 3 стороны пойти в общем случае. Но по памяти dfs оптимален - хранит только текущий путь. Как выше написали, путь асимптотически, это O(n*m). Меньше он может быть только если мы можем идти только вниз и вправо, тогда будет O(n+m), но тогда алгоритм менять не надо - мы больше памяти и не потратим в dfs. А если хочется быстрее, но памяти не жалко, можно заделать bfs, будет O(n*m) по сложности (в каждой ячейке мы побываем с алгоритмом максимум 1 раз), а по памяти не больше O((n*m)^2) Ну или можно в dfs запоминать "плохие" вершины, т.е. те, в которые мы заходили, и через которые точно не проходит оптимальный путь. Тогда в каждой вершине мы побываем до 4 раз и тогда сложность снова будет О(n*m). По памяти будет O(n*m). Может ты такое решение написал?
igors
Я бы двигался только вниз или вправо, зачем в три?
igors
Нам же надо из n,m координаты попасть в 1,1 координату
Владъ
Alexey
Эм... Но ведь dfs не будет по времени O(n*m) 😄 dfs перебирает все возможные траектории, пока не встретит нужную. Если нужной нет, то вообще все возможные и, кажется, их типа 3^(n+m), т.к. из каждой ячейки мы можем в 3 стороны пойти в общем случае. Но по памяти dfs оптимален - хранит только текущий путь. Как выше написали, путь асимптотически, это O(n*m). Меньше он может быть только если мы можем идти только вниз и вправо, тогда будет O(n+m), но тогда алгоритм менять не надо - мы больше памяти и не потратим в dfs. А если хочется быстрее, но памяти не жалко, можно заделать bfs, будет O(n*m) по сложности (в каждой ячейке мы побываем с алгоритмом максимум 1 раз), а по памяти не больше O((n*m)^2) Ну или можно в dfs запоминать "плохие" вершины, т.е. те, в которые мы заходили, и через которые точно не проходит оптимальный путь. Тогда в каждой вершине мы побываем до 4 раз и тогда сложность снова будет О(n*m). По памяти будет O(n*m). Может ты такое решение написал?
Да, я посещенные вершины уже отмечал, поэтому O(n*m) по времени написал, то есть я больше одного раза вершину посещать не буду
igors
предположим у нас грид 3x3 |0|1|0| |0|0|1| |1|0|0| (3,3) - верхняя левая кордината, из этой точки можем пойти или книз или вправо, тоесть только в две координаты (2,3) или (3,2)(только надо ещё дополнительно проверить, что значение в ячейке в которую перешли не равно 1) Итого можно построить двоичное дерево перемещения(сразу скажу визуализация так себе):
igors
igors
итого что получается что наша задача попасть в (1,1) точку
igors
итого высоты дерева получается - n+m
igors
а если эту задачку решать рекурсвно то space complexity = O(n+m)
igors
time complexity - O(m*n), если не посещать координаты - которые уже проходил
igors
по дереву это прекрасно видно
igors
лана я работать
igors
а то уволят)))
Alexey
Я не спорю, что среднее время скорее всего что-то между суммой и произведением, непонятно, что от меня хотели услышать
Alexey
А если грид 000 110 000 011 000 ?) А если 000 000 001 ?
Ну в последнем сразу отфильтровывается и будет null, так как первые проверки, что путь в целом возможен от начала в конец и там нули
igors
000 110 000 011 000 ?) - ну так в этом случаи нет MxN, тут что то среднее
Alexey
я говорил про порядок длины, а не точную длину пути. Тут длина больше N*M/2, то есть все равно O(N*M) по памяти получается из-за рекурсивных вызовов dfs
igors
ну или N+2*M что равно N+M
Владъ
Непонятно о чём спорите) Сложность может быть разная для лучшего и худшего случая. В таком случае указываются оба, а не «средняя» сложность
Anvar
Я думал когда говорят за сложность всегда имеется в виду асимптотическая сложность
Evgeniy
Так и есть
Evgeniy
О большое
Alexey
есть еще amortised time complexity, когда говорят про O большое, я это имел в виду, когда говорил про "среднюю" сложность
Alexey
немного неправильно выразился
Порридж В Ко-ливинге
лана я работать
Типо много "умного" текста, но базовый случай когда у тебя весь путь состоит из посещения N*M клеток эллэгантно проигнорировался
Порридж В Ко-ливинге
000 110 000 011 000 ?) - ну так в этом случаи нет MxN, тут что то среднее
ОООО. Сразу видно, человек на Литкоде решения со своей сложностью не выставлял. Там очередь из людей которые ведро дерьма готовы за такие рассуждения вылить. Сложность всегда худшая считается. Редко средняя, но это для алгоритмов сортировки
Порридж В Ко-ливинге
Больше критики чем на Leetcode только на Stackoverflow. Но на Литкоде она почти всегда обоснованная. Там не перфекционисты просто не выживают
Alexey
В общем, как бы то ни было, я жду фидбек и отпишусь, что из этого вышло))
Порридж В Ко-ливинге
000 110 000 011 000 ?) - ну так в этом случаи нет MxN, тут что то среднее
Когда ты посещяешь M×(N/2) или на 10 дели, всё равно итоговая big O сложность остаётся M×N Тебе не важно что за цифра там будет в начале, 10 или 5 или 1, у тебя куча нулей умножается на кучу нулей, а не складываетсч