Рубрики
Без рубрики

LeetCode в день – вертикальный порядок обход двоичного дерева

LeetCode Daily – 7 августа, 2020 г. Вертикальный заказ Обход двоичных деревьев на … Помечено JavaScript, CodeNewie, Challenge.

Вертикальный заказ обход двоичного дерева

Ссылка на вопрос летакода

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

Тем не менее, поскольку многие люди публикуют свои собственные решения в раздел дискуссий IETCODE, я не обязательно буду публиковать оптимальное решение.

Вопрос

( Копия вставлена из лецкода)

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

Для каждого узла в положении (X, Y) его левые и правые дети соответственно будут на позициях (x – 1, y-1) и (x + 1, y-1).

Запуск вертикальной линии от x = -infinity до x = + бесконечности, всякий раз, когда вертикальная линия касается некоторых узлов, мы сообщаем о значениях узлов в порядке сверху вниз (уменьшающиеся координаты Y).

Если два узла имеют одинаковое положение, то значение узла, которое сообщается, что сначала – это значение меньше.

Верните список непустых отчетов в порядке X координаты. Каждый отчет будет иметь список значений узлов.

Пример 1:

Input: [3,9,20,null,null,15,7]
Output: [[9],[3,15],[20],[7]]

Объяснение: Без потери общности мы можем предположить, что корневой узел находится в положении (0, 0): Затем узел со значением 9 происходит в положении (-1, -1); Узлы со значениями 3 и 15 происходят на позициях (0, 0) и (0, -2);

Узел со значением 20 встречается в положении (1, -1); Узел со значением 7 встречается в положении (2, -2).

Пример 2:

Input: [1,2,3,4,5,6,7]
Output: [[4],[2],[1,5,6],[3],[7]]

Объяснение: Узел со значением 5 и узел со значением 6 имеют одинаковое положение в соответствии с заданной схемой. Однако в отчете «[1,5,6]» значение узла 5 приходит первым с 5 меньше 6.

Примечания:

  • Дерево будет иметь от 1 до 1000 узлов.
  • Значение каждого узла будет от 0 до 1000.

Мой подход (ES)

Я не буду преодолевать весь код для всех попыток, но я объясню свой подход (ы) качественно.

Попытка 1 – DFS или BFS

(Представлено – принято)

Основываясь на подробных инструкциях, я понимаю, что каждый узел будет иметь собственную координату X и Y (относительно корневого узла). С этим пониманием я использовал первый поиск глубины, чтобы найти бинарное дерево и добавить каждый узел в структуру данных. Я использовал объект JavaScript, который имеет характеристики хэш таблицы, чтобы держать данные о каждом узле.

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

Я хотел, чтобы мой контейнер выглядел что-то подобное, после того, как он был заполнен (используя примерные значения 1):

 const xCoordMap = {
   "-1": [{val:9, y:-1}],
   "0": [{val:3, y:0}, {val:15, y:-2}],
   "1": [{val:20, y:1}],
   "2": [{val:7, y:2}]
 }

Первоначально я пытался использовать широкий поиск первого поиска, потому что этот алгоритм поиска ищет все узлы того же уровня Y, последовательно. Однако, когда есть галстук в Y значение Y, вопрос хочет, чтобы значение более низкого узла было установлено первым. Поэтому я закончил запись значений Y, чтобы обнаружить связи, а затем сначала отсортировала их самым высоким значением y, а затем самым низким значением (если значения Y привязаны).

Представляемый код JavaScript:

var verticalTraversal = function(root) {
    // dfs or bfs but calculate the coordinates while running it 
    // using bfs we won't have to use the Y values to sort (?)
    // left goes to X-1, Y-1, right goes to X+1, Y-1 
    let stack = [{...root, x: 0, y:0}];

    let xCoordMap = {}

    const addNode = (val, x, y) => {
        // if the key, 'x', already exists, push it 
        // if it doesn't, make a new array 
        if (xCoordMap[`${x}`]) {
            xCoordMap[`${x}`].push({val, y});
        } else {
            xCoordMap[`${x}`] = [{val, y}];
        }
    }


    while (stack.length > 0) {

        const currNode = stack.pop();

        addNode(currNode.val, currNode.x, currNode.y);

        if (currNode.left) {
            stack.push({...currNode.left, x: currNode.x - 1, y: currNode.y - 1});
        }

        if (currNode.right) {
            stack.push({...currNode.right, x: currNode.x + 1, y: currNode.y - 1});
        }

    }

    // we have an object with numbered keys and arrays of values 
    const sortedKeys = Object.keys(xCoordMap).sort((a,b) => Number(a) - Number(b));
    const vertArrays = sortedKeys.map(key => {
       // sort the array then return it with only vals, not x and y 
       // sort by y first, then by value if y's are the same 
       xCoordMap[key].sort((a,b) => b.y - a.y).sort((a,b) => {
           if (a.y === b.y) return a.val - b.val;
           return 0;
       })
       return xCoordMap[key].map(obj => obj.val);
    });
    return vertArrays;
};

Обсуждение и выводы

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

Однако я мог бы сделать еще несколько думать о сортировке массивов моего узла контейнера по значению Y и значение узла при добавлении, а не перед возвратом. Я верю, что смогу сделать это в O (n), если бы я попытался поставить новые узлы в правильном месте при добавлении их вместо o (nlog (n)) сортировки, что я сделал, чтобы вернуть решение.

Оригинал: “https://dev.to/drewhsu86/leetcode-daily-vertical-order-traversal-of-binary-tree-3d8j”