Используя уникальный отсортированный список целых чисел, создайте сбалансированное дерево двоичного поиска, представленное в виде массива, без использования рекурсии.
Например:
func( [1,2,3,5,8,13,21] ) => [5,2,13,1,3,8,21]
Прежде чем мы начнем, подсказка: мы можем упростить эту проблему до тонны, так что нам на самом деле не нужно думать о входных целых числах (или любом подобном объекте в этом отношении!)
Если мы знаем, что входной список уже отсортирован, его содержимое не имеет значения. Мы можем просто думать об этом с точки зрения индексов в исходном массиве.
Внутреннее представление входного массива становится:
func( [0,1,2,3,4,5,6] ) => [3,1,5,0,2,4,6]
Это означает, что вместо того, чтобы писать что-то, имеющее дело с сопоставимыми объектами, нам действительно нужно написать только функцию, которая отображается из диапазона [0, n) в результирующий массив. Получив новый порядок, мы можем просто применить отображение обратно к значениям во входных данных, чтобы создать возвращаемый массив.
Действительные решения должны:
- Примите массив с нулевым элементом и верните пустой массив.
- Примите целочисленный массив длины n и верните целочисленный массив
- Длина между n и следующей наибольшей степенью 2 минус 1. (например, для входного размера 13 верните где-нибудь между 13 и 15).
- Массив, представляющий BST, где корневой узел находится в позиции 0, а высота равна log (n), где 0 представляет отсутствующий узел (или
null
-подобное значение, если позволяет ваш язык). Пустые узлы, если они есть, должны существовать только в конце дерева (например,[2,1,0]
)
Входной целочисленный массив имеет следующие гарантии:
- Значения - это 32-разрядные целые числа со знаком, больше нуля.
- Ценности уникальны.
- Значения в порядке возрастания от нулевой позиции.
- Значения могут быть разреженными (то есть не смежными друг с другом).
Побеждает самый лаконичный код по количеству символов ascii, но мне также интересно увидеть элегантные решения для любого конкретного языка.
Контрольные примеры
Выходы для простых массивов , содержащих , 1
чтобы n
для различных n
. Как описано выше, завершающие 0
s являются необязательными.
[]
[1]
[2,1,0]
[2,1,3]
[3,2,4,1,0,0,0]
[4,2,5,1,3,0,0]
[4,2,6,1,3,5,0]
[4,2,6,1,3,5,7]
[5,3,7,2,4,6,8,1,0,0,0,0,0,0,0]
[6,4,8,2,5,7,9,1,3,0,0,0,0,0,0]
[7,4,9,2,6,8,10,1,3,5,0,0,0,0,0]
[8,4,10,2,6,9,11,1,3,5,7,0,0,0,0]
[8,4,11,2,6,10,12,1,3,5,7,9,0,0,0]
[8,4,12,2,6,10,13,1,3,5,7,9,11,0,0]
[8,4,12,2,6,10,14,1,3,5,7,9,11,13,0]
[8,4,12,2,6,10,14,1,3,5,7,9,11,13,15]
источник
Ответы:
Руби , 143
Это (слабо) сжатая версия следующего кода, которая в основном выполняет BFS для дерева.
Кроме того, поскольку это BFS, а не DFS, требование нерекурсивного решения не является значительным и ставит некоторые языки в невыгодное положение.
Изменить: Исправленное решение, спасибо @PeterTaylor за его комментарий!
источник
Ява , 252
Хорошо, вот моя попытка. Я играл с битовыми операциями и придумал прямой способ вычисления индекса элемента в BST по индексу в исходном массиве.
Сжатая версия
Длинная версия следует ниже.
источник
int[] b(int[] a)
так же хорошо выражен, какint[]b(int[]a)
.a.length
в массиве выделение. Измените это наs
. Избавьтесь от пространства междуfor (
несколькими разами. Каждый цикл for создает такжеint i=0
иint t=0
. Создайте с помощьюn
(int n=0,i,t;
), а затем простоi=0
в циклах иt=1
внутри. Объявите внутреннееlong x
иlong I
сs
и просто инициализируйте в цикле (long s=a.length,I,x;
иx=..
/I=..
). Вы не должны пространства вокруг двойных и&
.I=I|..
можно написатьI|=..
источник
Не совсем уверен, что это точно соответствует вашему требованию, чтобы пустые узлы были в конце дерева, и он, конечно, не выиграет никаких призов за краткость, но я думаю, что это правильно и имеет тестовые примеры :)
источник
Golfscript (
9989)В основном прямой порт моего решения на Python, работает почти так же.
Вероятно, можно немного улучшить с помощью большего количества «гольфизмов», уже улучшенных на 10 символов с помощью @ petertaylor :)
источник
!{;}{}if
может быть просто!{;}*
потому, что!
гарантирует возврат0
или1
. Вы можете использовать не алфавитные токены для переменных, поэтому, если вы используете^
вместоr
,|
вместоx
,&
вместо,y
вы можете устранить все эти пробелы.Ява 192
Сопоставляет индекс на входе с индексом на выходе
Длинная версия:
источник
Wolfram Mathematica 11, 175 байт
Функция
g[l]
принимает в качестве входных данных aList
(напримерl={1,2,3,4,...}
) и возвращает aList
желаемой формы. Это работает следующим образом:x[a_]:=Floor@Min[i-#/2,#]&@(i=Length[a]+1;2^Ceiling@Log2[i]/2)
берет список и находит корень связанного BST.i=Length[a]+1
сокращение длины списка2^Ceiling@Log2[i]/2
верхняя граница значения корняMin[i-#/2,#]&@(...)
Минимум из двух аргументов, где#
обозначает то, что находится внутри(...)
l//.{...}
Примените повторно правила замены, которые следуютl
{}->{}
Ничего не делать (это крайний случай, чтобы избежать бесконечного цикла)b__List:>(n[Take[b,#-1],b[[#]],Drop[b,#]]&@x[b])
РазделитьList
на{{lesser}, root, {greater}}
Cases[...,_Integer,{m}]
Возьмите все целые числа на уровне (глубине)m
Table[...,{m,1,x[l]}]
Для всехm
доx[l]
(что более чем необходимо на самом деле).Это можно проверить, запустив
Эта реализация не включает конечные нули.
источник
Питон (
175171)Довольно сжатый, все еще довольно читаемый;
Он возвращает результат обратно, так что вы можете либо зациклить его, либо (для целей отображения) напечатать его в виде списка;
источник
Джава
Это прямое решение для расчета. Я думаю, что это работает, но у него есть один прагматически безобидный побочный эффект. Массив, который он создает, может быть поврежден, но никак не повлияет на поиск. Вместо создания 0 (нулевых) узлов, он будет создавать недоступные узлы, то есть узлы уже были найдены ранее в дереве во время поиска. Он работает путем сопоставления массива индексов массива двоичного дерева поиска 2-й степени с массивом двоичного дерева поиска неправильного размера. По крайней мере, я думаю, что это работает.
Вот более сжатая версия (только функция и имена в паре). У него все еще есть белое пространство, но я не беспокоюсь о победе. Также эта версия на самом деле принимает массив. Другой просто взял int для самого высокого индекса в массиве.
источник
GolfScript (
79 7770 символов)Так как пример в вопросе использует функцию, я сделал это функцией. Удаление,
{}:f;
чтобы оставить выражение, которое принимает ввод в стек и оставляет BST в стеке, спасло бы 5 символов.Демонстрация в Интернете (примечание: приложению может потребоваться некоторое время для разогрева: оно истекло у меня дважды перед запуском в 3 секунды).
С пробелами, чтобы показать структуру:
источник
J , 52 байта
функция принимает отсортированный список и возвращает в двоичном порядке дерева
обратите внимание, что деревья имеют одинаковую форму, но нижний уровень укорочен
`1:
начать с 1<.@(2&^.)@>:@#
итерация по этажу log2 (длина + 1)+: , >:@+:@i.@>:@#
цикл: добавляет дубль последнего вектора с нечетными числами 1,3 .. 2 * длина + 1# /:@{.
взять только необходимое количество предметов и получить их индексы сортировки/:
применить эти индексы сортировки к данному входуTIO
источник
Python 2 , 107 байт
Гольф от Иоахима Исакссона: вход - это синглтон, содержащий список.
Попробуйте онлайн!
источник