Высота дерева предсказуема roundUp(log2(nodes))
. Мы также знаем, что правое поддерево никогда больше левого поддерева - |LS| >= |RS|
. Более того, мы можем вычислить количество узлов, которые отсутствуют, чтобы сделать дерево идеальным: 2^(height - 1) - arr.length
. Это позволяет предсказать, как распределить узлы среди поддеревьев:
findRoot(int[] arr , int maxLeaves , int maxLevelL)
//maxLeaves is the number of leaves on the maximum-level
int l = min(maxLevelL/2 , maxLeaves)
return (arr.length - maxLeaves)/2 + l
node buildTree(int[] arr , int maxLeaves , int maxLevelL)
if maxLevelL == 0
return null
node result
int rootidx = findRoot(arr , maxLeaves)
result.val = arr[rootidx]
result.left = buildTree(arr.subarray(0 , rootidx) , Math.min(maxLeaves , rootidx - 1) , maxLevelL/2)
result.right = buildTree(arr.subarray(rootidx + 1 , arr.length) , Math.max(0 , maxLeaves - rootidx - 1) , maxLevelL/2)
return node
Основная идея заключается в следующем: все полные BSTs разделяют одно свойство, о рекурсивном определении BST: (LS , R , RS) OR null
, где LS
и RS
являются левая и правое поддерево, которые также определены как BST. Оба LS
и RS
являются полными и по крайней мере один из них должен быть идеальным. Мы можем легко предсказать, какой из двух идеален: на самом высоком уровне подходят m
узлов, но в массиве нам не хватает x
узлов для создания идеального дерева. Таким образом:
if m - x == m/2 then both are complete and the height of RS is height(LS) - 1
if m - x < m/2 RS is perfect, LS only complete but not perfect
if m - x > m/2 LS is perfect, RS only complete but not perfect
if m - x == 0 both LS and RS are perfect and of equal height
Мы можем найти корень дерева, используя следующее правило: Подсчитать количество узлов на левой (l
) и вправо (r
) поддерева, которые будут размещены на уровне heighest. Теперь мы можем легко удалить эти узлы из дерева, вычислить корень совершенного BST, а затем добавить левые и правые узлы обратно в дерево неявно: root = (arr.length - (l + r))/2 + l
E.g.:
Input: 1 2 3 4 5
Nodes on maxLevel: 2
maxLevelL: 4
l = 2
r = 0
root_idx = (arr.length - (l + r))/2 + l =
= (5 - 2)/2 + 2 =
= 3
Apply this algorithm recursively to define subtrees:
...
result:
4
/ \
2 5
/ \
1 3
Примечание: Я не проверял этот код. Возможно, он все еще содержит несколько арифметических недостатков, которые необходимо устранить. Однако логика правильная. Это должно просто представлять способ переназначения индексов из одного массива в другой. Фактическая реализация может сильно отличаться от кода, который я предоставил.
После этого обсуждения во второй раз, вот определение полного BST:
В полном бинарном дереве каждого уровня, за исключением, возможно, последним, полностью заполнена, и все узлы в последнем уровень как можно дальше.
from wikipedia
Полного BSTs подкласс сбалансированного BSTs, с некоторыми дополнительными ограничениями, которые позволяют уникальное отображение полного BST в отсортированный массив, и наоборот. Поскольку полные BST являются только подклассом сбалансированных BST, то не будет, чтобы построить сбалансированный BST.
РЕДАКТИРОВАТЬ:
приведенный выше алгоритм может быть изменен следующим образом, чтобы непосредственно построить массив:
- корень дерева имеет индекс 0
- левый ребенок узла с индексом
n
имеет индекс (n + 1) * 2 - 1
- право ребенка узла с индексом
n
имеет индекс (n + 1) * 2
Обычно эти доступ-операции выполняются на массиве 1 на основе, но я изменил их, чтобы соответствовать массиву 0 на основе для удобства
Таким образом, мы можем повторно buildTree
непосредственно производить массив:
node buildTree(int[] arr , int maxLeaves , int maxLevelL ,
int[] result , int nodeidx)
if maxLevelL == 0
return
int rootidx = findRoot(arr , maxLeaves)
//insert value into correct position of result-array
result[nodeidx] = arr[rootidx]
//build left subtree
buildTree(arr.subarray(0 , rootidx) , Math.min(maxLeaves , rootidx - 1) , maxLevelL/2 ,
result , (nodeidx + 1) * 2 - 1)
//build right subtree
buildTree(arr.subarray(rootidx + 1 , arr.length) , Math.max(0 , maxLeaves - rootidx - 1) , maxLevelL/2 ,
result , (nodeidx + 1) * 2)
Обратите внимание, что в отличие от arr
, мы никогда не используем подмассивы result
. Индексы соответствующих узлов никогда не изменяются во всех методах-вызовах.
Go с чем-то неявным отображением, которое использует разделяй и властвуйте: Карту номера элемента круглой (размер/2) к корню, применить неявную функцию на левой стороне массива для левого ребенка, правая сторона для правильного ребенка. – Aziuth
@Aziuth, который не приведет к полному BST, но сбалансированному BST. полные BST являются подклассом сбалансированного BST, а не эквивалентом. – Paul