/** * Удаляет узел со значением `key` из BST и возвращает (возможно новый) корень. * * Сложность по времени: O(h), где h — высота дерева. * - Поиск удаляемого узла идёт по одному пути вниз (сравнения key с root.val), это O(h). * - Если у узла 2 ребёнка, мы дополнительно ищем inorder successor: минимум в правом поддереве (идём вправо 1 раз, затем “влево до упора”), это тоже O(h) в худшем случае. * - Затем удаляем successor рекурсивно в правом поддереве; это ещё один проход по высоте, но суммарно всё равно остаётся O(h) (константное число проходов по высоте). * - В несбалансированном дереве h может быть n, поэтому худший случай по времени — O(n); в сбалансированном — O(log n). * * Сложность по памяти: O(h) из-за глубины рекурсии (стек вызовов). * - В худшем случае O(n) для “списка”, в сбалансированном O(log n). */var deleteNode = function(root, key) { if (!root) return null; if (key < root.val) { root.left = deleteNode(root.left, key); } else if (key > root.val) { root.right = deleteNode(root.right, key); } else { if (!root.left) return root.right; if (!root.right) return root.left; // ВАЖНО: здесь должен быть let, потому что переменную мы двигаем по дереву let newNode = root.right; while (newNode.left) { newNode = newNode.left; } root.val = newNode.val; root.right = deleteNode(root.right, newNode.val); } return root;};