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

Решение: построить двоичное дерево из предварительного заказа и обхода в заказ

Это является частью серии объяснений решений LeetCode (индекс). Если вам понравилось это решение или fou … с меткой алгоритмы, JavaScript, Java, Python.

Это является частью серии объяснений решения LeetCode ( index ). Если вам понравилось это решение или нашли его полезным, Пожалуйста, нравится Этот пост и/или upvote Мое решение по сообщению на форумах LeetCode Анкет

Проблема LeetCode #105 (Среда): построить двоичное дерево из предварительного заказа и обхода на заказ

Описание:

( прыгнуть в : Идея решения Код : JavaScript | Python | Java | C ++

Учитывают два целочисленных массива предварительный заказ и inorder где предварительный заказ это предварительное прохождение бинарного дерева и inorder это обход по заказу одного и того же дерева, построить и вернуть двоичное дерево Анкет

Примеры:

Вход: предварительный заказ = [3,9,20,15,7], inorder = [9,3,15,20,7]
Выход: [3,9,20, NULL, NULL, 15,7]
Визуальный:
Вход: предварительный заказ = [-1], inorder = [-1]
Выход: [-1]

Ограничения:

  • 1. длиной
  • inorder.length.length
  • -3000 [i], inorder [i]
  • предварительный заказ и inorder состоят из уникальных значений.
  • Каждое значение inorder Также появляется в предварительный заказ Анкет
  • предварительный заказ гарантированно будет предварительным проходом дерева.
  • inorder гарантированно будет облицовка дерева.

Идея:

( Прыгните к : Описание задачи Код : JavaScript | Python | Java | C ++

Для этого решения мы можем воспользоваться порядок узлов в предварительный заказ и inorder проходы. Предварительный заказ – это [Узел, слева, справа] в то время как обход по заказу – это [Слева, Узел, справа] Анкет

Мы знаем, что корень Узел для дерева является первым элементом массива предварительного заказа ( P ). Мы также знаем, что каждый элемент слева от корневого элемента в массиве Inorder ( i ) находится на левой поддерею, и все справа от корень элемент в Я находится на правом поддерево.

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

С этой информацией мы можем определить рекурсивный вспомогательная функция ( SplitTree ) это разделяет дерево на два, а затем рекурсивно сделает то же самое для каждого поддерева.

Чтобы сделать эту работу, нам просто нужно пройти влево и правое ограничения ( ilft, iright ) Определение субаррея текущего поддерева в Я , а также индекс ( pix ) из корень Узел поддерево в P .

На данный момент мы мог переходить вперед через Я Пока мы не узнаем местоположение ( imid ) из корень Узел каждый раз, но это подтолкнет это решение к Сложность времени из O (n^2) Анкет

Вместо этого мы можем сделать предварительное место Индексная карта ( m ) значений в Я , чтобы мы могли искать значение для имид в O (1) время в каждой рекурсии. Это снизит сложность времени до O (n) за счет Сложность пространства из O (n) Анкет

В примере на графике выше, где P = [8,2,7,1,9,3,6] и I = [7,2,1,8,3,9,6] , корень было бы 8 , Итак, мы знаем, что Imid (его местоположение в Я ) это 3 , и так как мы все еще используем полный массив, Ileft и iright.length-1 , или 6 Анкет Это означает, что левый поддерек – это Imid – Элементы долго ( [7,2,1] слева от 8 in Я ) и правильная поддерево Iright – Элементы длинные ( [3,9,6] справа от 8 I ).

Мы можем применить эти измерения из Я выяснить диапазоны этих подтереев в P , также. Левый поддерек начнется сразу после корень в P ( pix + 1 ), и правая подтерек запустится, как только левое подтерее завершится ( pix + 1 + (imid – ilft) .

При каждой рекурсии, если Imid Тогда в левом поддерере нет узлов, поэтому мы не должны вызывать рекурсию для этой стороны. То же самое относится и к правой стороне, если имид .

  • Сложность времени: O (n) куда N является длиной P и I
  • Сложность пространства: O (n) за M

Код JavaScript:

( Прыгните к : Описание задачи Идея решения

var buildTree = function(P, I) {
    let M = new Map()
    for (let i = 0; i < I.length; i++)
        M.set(I[i], i)
    return splitTree(P, M, 0, 0, I.length-1)
};

var splitTree = function(P, M, pix, ileft, iright) {
    let rval = P[pix],
        root = new TreeNode(rval),
        imid = M.get(rval)
    if (imid > ileft)
        root.left = splitTree(P, M, pix+1, ileft, imid-1)
    if (imid < iright)
        root.right = splitTree(P, M, pix+imid-ileft+1, imid+1, iright)
    return root
}

Код Python:

( Прыгните к : Описание задачи Идея решения

class Solution:
    def buildTree(self, P: List[int], I: List[int]) -> TreeNode:
        M = {I[i]: i for i in range(len(I))}
        return self.splitTree(P, M, 0, 0, len(P)-1)

    def splitTree(self, P: List[int], M: dict, pix: int, ileft: int, iright: int) -> TreeNode:
        rval = P[pix]
        root, imid = TreeNode(rval), M[rval]
        if imid > ileft:
            root.left = self.splitTree(P, M, pix+1, ileft, imid-1)
        if imid < iright:
            root.right = self.splitTree(P, M, pix+imid-ileft+1, imid+1, iright)
        return root

Код Java:

( Прыгните к : Описание задачи Идея решения

class Solution {
    public TreeNode buildTree(int[] P, int[] I) {
        Map M = new HashMap<>();
        for (int i = 0; i < I.length; i++)
            M.put(I[i], i);
        return splitTree(P, M, 0, 0, I.length-1);
    }

    private TreeNode splitTree(int[] P, Map M, int pix, int ileft, int iright) {
        int rval = P[pix], imid = M.get(rval);
        TreeNode root = new TreeNode(rval);            
        if (imid > ileft)
            root.left = splitTree(P, M, pix+1, ileft, imid-1);
        if (imid < iright)
            root.right = splitTree(P, M, pix+imid-ileft+1, imid+1, iright);
        return root;
    }
}

C ++ Код:

( Прыгните к : Описание задачи Идея решения

class Solution {
public:
    TreeNode* buildTree(vector& P, vector& I) {
        unordered_map M;
        for (int i = 0; i < I.size(); i++)
            M[I[i]] = i;
        return splitTree(P, M, 0, 0, I.size()-1);
    }

private:
    TreeNode* splitTree(vector& P, unordered_map& M, int pix, int ileft, int iright) {
        int rval = P[pix], imid = M[rval];
        TreeNode* root = new TreeNode(rval);            
        if (imid > ileft)
            root->left = splitTree(P, M, pix+1, ileft, imid-1);
        if (imid < iright)
            root->right = splitTree(P, M, pix+imid-ileft+1, imid+1, iright);
        return root;
    }
};

Оригинал: “https://dev.to/seanpgallivan/solution-construct-binary-tree-from-preorder-and-inorder-traversal-32c5”