Порридж В Ко-ливинге
Sergei
Что-то у меня беда с рекурсивным обходом дерева, похоже что-то упускаю
Viktor
там надо через рекурсивные вызовы передавать индекс текущего уровня, чтобы правильно положить на нужный уровень.
Sergei
Да в сегодняшней, но я думаю, у меня в целом с обходом беда)
Viktor
иначе не понятно, что именно тебе не понятно.
Sergei
Идея такая, если нет детей, то мы возвращаем значение, в если дети есть то мы идём глубже и возвращаем уже массив с средним значение. <code> var averageOfLevels = function(root, result = [root.val]) { if(root.left == null && root.right == null) { return root.val; } const left = averageOfLevels(root.left, result); const right = averageOfLevels(root.right, result); if(!Array.isArray(left) && !Array.isArray(right)) { const avg = (left + right) / 2; result.push(avg); } // если вернулся массив слева или справа, то... return result; }; </code>
Sergei
Но я уже перемудрил
Sergei
И сломался
Viktor
Идея такая, если нет детей, то мы возвращаем значение, в если дети есть то мы идём глубже и возвращаем уже массив с средним значение. <code> var averageOfLevels = function(root, result = [root.val]) { if(root.left == null && root.right == null) { return root.val; } const left = averageOfLevels(root.left, result); const right = averageOfLevels(root.right, result); if(!Array.isArray(left) && !Array.isArray(right)) { const avg = (left + right) / 2; result.push(avg); } // если вернулся массив слева или справа, то... return result; }; </code>
мне кажется, что главное что ты упускаешь — порядок в котором будет обход. рекурсия будет идти сперва все время в левую ветку, до конца, поэтому и называется обход в глубину, как следствие, у тебя уровни будут перепутаны. то есть тебе надо по горизонтали как бы смотреть, а обходишь ты по вертикали сперва.
Viktor
для этого вторым аргументом в функцию обхода передаётся level, просто индекс текущего уровня, с помощью которого можно найти нужны сумму в мапе и её менять.
Viktor
мапа с уровнями где ключи индексы, а значения структурки с двумя полями sum и count, чтобы считать сумму и количество
Viktor
и в конце уже можно используя эти знания найти среднее
Viktor
на каждом уровне
Sergei
Спасибо, буду мучать дальше
Viktor
мапа с уровнями где ключи индексы, а значения структурки с двумя полями sum и count, чтобы считать сумму и количество
я сперва складывал на каждый уровень сами значения узлов, в массивы, а среднее считал в конце. но потом понял, что сами значения и не нужны, можно сразу сумму считать и количество.
Viktor
порядок не важен, так что удобно.
Evgeniy
Я считал в словаре количество элементов на каждом уровне. И еще в листе сумму значений этого уровня
Viktor
Спасибо, буду мучать дальше
ещё может помочь такая штука, по крайней мере для меня работает: просто напиши обход как сейчас, который ничего не делает, а только печатает значение root.val и ты увидишь в каком порядке печатаются числа и намапишь на значения в дереве на картинке — сразу становится ясно в каком порядке рекурсия обходит узлы
Evgeniy
А потом так: return sums.Select((s,level) => (double)s / counts[level]).ToList();
Ilia
Вот это хороший вариант для старта
вот нагляднее bfs vs dfs, мне такая иллюстрация когда-то очень помогла
Viktor
Фига выстрелило
Бабичев заапрувил. Это успех.
Sergei
Тут preorder DFS, самый популярный
Подскажи, пожалуйста, зачем разные типы обходов? In, pre, post, от задач зависит?
Evgeniy
var findAllConcatenatedWordsInADict = function(words) { const trie = new Trie(); function dfs(word, start, chainLen) { if (word.length == start) { // нужно убедиться, что нашли больше чем одно слово в цепочке return chainLen > 1; } let curr = trie.root; for (let i = start; i < word.length; i++) { curr = curr.get(word[i]); // если в дереве нет следующем буквы, // значит нет ни одного слова для продолжения if (!curr) { return false; } // если это лист, надо попборовать снова поискать все дерево // в поиске следующих слов, только отрезав уже найденный «префикс» if (curr.isLeaf && dfs(word, i + 1, chainLen + 1)) { return true; } } return false; } const result = []; // оптимизация, которая позволит // исключить TLE для кейса с общими префиксами: // a, aa, aaa, aaaa, aaaaa, ... // имеет смысл добавлять слова в трай постепенно, // т.к. в любом случае маленькие слова нельзя побить большими, // соответственно и в дереве они раньше времени не нужны words.sort((a, b) => a.length - b.length); words.forEach((word) => { if (dfs(word, 0, 0)) { result.push(word); } else { trie.add(word); } }); return result; }; class Trie { root = new Node("") add(word) { let curr = this.root; for (let i = 0; i < word.length; i++) { curr = curr.add(word[i]); } curr.isLeaf = true; } } class Node { isLeaf = false; children = new Array(26); constructor(val) { this.val = val; } add(val) { const idx = this.idx(val); if (!this.children[idx]) { this.children[idx] = new Node(val); } return this.children[idx]; } get(val) { return this.children[this.idx(val)]; } idx(val) { return val.charCodeAt(0) - 'a'.charCodeAt(0); } }
Мысль с "повторным заходом" в Trie тоже была. Волновало, пройдет ли такая глубокая рекурсия. Оптимизация с сортировкой по длине действительно хороша! 👍
Evgeniy
Подскажи, пожалуйста, зачем разные типы обходов? In, pre, post, от задач зависит?
Да. Например есть задача на литкоде, где нужно посчитать путь с максимальной суммой значений в узлах (или максимальной длины, не помню). Так вот, для этой задачи можно использовать postorder dfs. Мы считаем максимальный путь от нашего корня в левую сторону (в левый потомок). А потом в правую. А потом суммируем и передаем дальше вверх по дереву.
Evgeniy
Чаще всего используется preorder. Пришел, посчитал, пошел дальше
Evgeniy
Реализацией они отличаются совсем немного (если рекурсивно писать). По ходу решения задачи уже можно сообразить какой вариант предпочтительнее
Alexandr
Или например BST + inorder, чтобы вывести значения в отсортированном порядке, полезно знать :)
Evgeniy
Подскажи, пожалуйста, зачем разные типы обходов? In, pre, post, от задач зависит?
Вот нашел: https://leetcode.com/problems/binary-tree-maximum-path-sum/discuss/603039/C-simple-recursive-postorder-DFS-solution
Sergei
Спасибо, порешаю)
Evgeniy
Спасибо, порешаю)
Попробуй еще вот эту задачу. И с ней связанные. https://leetcode.com/problems/path-sum/
Ilia
а давно в литкоде появились визуалайзеры?
Ilia
например для дерева в сегодняшней задачке
Порридж В Ко-ливинге
Viktor
🔥
Alex Azarov
А у меня ноут отобрали, а на новую работу ещё не анборднулся, решаю с телефона литкод чтобы страйк не пропал
Viktor
до сих пор на нём и сижу. плюс к рабочему теперь уже.
Ilia
неплохо. я выкупил свой когда увольнялся.
хорошо, когда такая возможность есть
Viktor
хорошо, когда такая возможность есть
ага, вроде в Яндексе это стандартная практика.
Viktor
их бы в любом случае списали в утиль, а так люди покупают, че.
Ilia
ну если еще и вменяемой цене ниже рынка то вин-вин для всех, круто
Viktor
именно. в 2018 году купил, по-моему, за 34 тысячи рублей, MacBook Pro (Retina, 13-inch, Mid 2014)
Viktor
по-божески.
Alex Azarov
ага, вроде в Яндексе это стандартная практика.
Хз, мне не дали выкупить, как я понял можно выкупать только старые модели
Ilia
именно. в 2018 году купил, по-моему, за 34 тысячи рублей, MacBook Pro (Retina, 13-inch, Mid 2014)
норм, я пару месяцев назад на авито mid2013 за 35 продал )
Порридж В Ко-ливинге
неплохо. я выкупил свой когда увольнялся.
Так вроде именно свой нельзя. Выкупаешь со скидкой?
Порридж В Ко-ливинге
Я опять не в офисе и вики не под рукой)
Viktor
Так вроде именно свой нельзя. Выкупаешь со скидкой?
ну, свой — который был у меня тогда на руках. рабочий.
Порридж В Ко-ливинге
Порридж В Ко-ливинге
А можно только свой выкупить, иои вообще можно купить у них?
Порридж В Ко-ливинге
Ладно, завтра пойду работать, почитаю на вики
Порридж В Ко-ливинге
Даже в выходной работать?
Ну, я хочу таски закрыть, и может еще посмотреть как у нас бэкэнд выглядит
Viktor
Даже в выходной работать?
человеку 20 лет, как же иначе!
Viktor
я бы удивился если бы он не работал в выходные
Порридж В Ко-ливинге
Я еще щас ЕГЭ буду делать 😃
Порридж В Ко-ливинге
Щас в МФТИ поступлю, выкуплю ноут, и буду студентом год, два)
Andrey
человеку 20 лет, как же иначе!
Мне не понять. В 20 лет вокруг много интересного помимо работы. Ну, во всяком случае у меня так было
Порридж В Ко-ливинге
А потом академ возьму, чтобы еще по карьериться годик, только уже в Гугле
Порридж В Ко-ливинге
Мне не понять. В 20 лет вокруг много интересного помимо работы. Ну, во всяком случае у меня так было
Ой, я до 18 лет таки пинал... Что мне щас кроме работы и учебы ничего не хочется
Порридж В Ко-ливинге
Девушка есть, в игры не играю (хотя очень хочу), друзей нет, что мне еще делать? 🤣
Порридж В Ко-ливинге
Про медицину читаю, вон мне ПХРД написали, давай пугать что солепну, а я давай лекции в захлеп смотреть да статьи читать, оказалось что это не так страшно
Viktor
Мне не понять. В 20 лет вокруг много интересного помимо работы. Ну, во всяком случае у меня так было
Какие-то страшные вещи говоришь, что может быть интереснее литкода 😂
Порридж В Ко-ливинге
Порридж В Ко-ливинге
может закончить лучше сперва? 😄
Ну... Мне страшна мысль что я вот 3 года уже в этом кручусь, а щас просто на 4 года выпаду, так хоть прерываться буду, опыт в сфере подтверждать