Dada uma lista exclusiva e ordenada de números inteiros, crie uma árvore de pesquisa binária equilibrada representada como uma matriz sem usar recursão.
Por exemplo:
func( [1,2,3,5,8,13,21] ) => [5,2,13,1,3,8,21]
Antes de começarmos, uma dica: podemos simplificar muito esse problema para que não tenhamos que pensar nos números inteiros de entrada (ou em qualquer objeto comparável a esse respeito!).
Se sabemos que a lista de entrada já está classificada, seu conteúdo é irrelevante. Podemos simplesmente pensar sobre isso em termos de índices na matriz original.
Uma representação interna da matriz de entrada se torna:
func( [0,1,2,3,4,5,6] ) => [3,1,5,0,2,4,6]
Isso significa que, em vez de escrever algo que tenha que lidar com objetos comparáveis, precisamos realmente apenas escrever uma função que mapeie do intervalo [0, n) à matriz resultante. Depois de termos a nova ordem, podemos simplesmente aplicar o mapeamento aos valores na entrada para criar a matriz de retorno.
As soluções válidas devem:
- Aceite uma matriz de elemento zero e retorne uma matriz vazia.
- Aceite uma matriz inteira de comprimento n e retorne uma matriz inteira
- De comprimento entre n e a próxima potência mais alta de 2 menos 1. (por exemplo, para o tamanho de entrada 13, retorne entre 13 e 15).
- Matriz que representa um BST em que o nó raiz está na posição 0 e a altura é igual a log (n) em que 0 representa um nó ausente (ou um
null
valor semelhante, se o seu idioma permitir). Nós vazios, se presentes, devem existir apenas no final da árvore (por exemplo,[2,1,0]
)
A matriz inteira de entrada possui as seguintes garantias:
- Os valores são números inteiros assinados de 32 bits maiores que zero.
- Os valores são únicos.
- Os valores estão em ordem crescente a partir da posição zero.
- Os valores podem ser escassos (ou seja, não adjacentes um ao outro).
O código mais conciso pela contagem de caracteres ascii vence, mas também estou interessado em ver soluções elegantes para qualquer idioma em particular.
Casos de teste
As saídas para matrizes simples que contêm 1
to n
para vários n
. Como descrito acima, os valores finais 0
são opcionais.
[]
[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]
fonte
Respostas:
Ruby , 143
É uma versão compactada (vagamente) do código a seguir que basicamente executa um BFS na árvore.
Além disso, por ser BFS, não DFS, um requisito de solução não recursiva não é significativo e coloca alguns idiomas em desvantagem.
Edit: Solução fixa, obrigado a @ PeterTaylor por seu comentário!
fonte
Java , 252
Ok, aqui está a minha tentativa. Eu tenho brincado com operações de bits e criei essa maneira direta de calcular o índice de um elemento no BST a partir do índice na matriz original.
Versão compactada
A versão longa segue abaixo.
fonte
int[] b(int[] a)
é tão bem expresso quantoint[]b(int[]a)
.a.length
na alocação de matriz. Mude paras
. Livre-se do espaçofor (
várias vezes. Cada loop for cria umint i=0
e tambémint t=0
. Crie comn
(int n=0,i,t;
) e depois apenasi=0
nos loops et=1
dentro. Declare o interiorlong x
elong I
coms
e apenas inicialize no loop (long s=a.length,I,x;
ex=..
/I=..
). Você não deve precisar de espaços ao redor do binário AND&
.I=I|..
pode ser escritoI|=..
fonte
Não tenho certeza se isso se encaixa exatamente no seu requisito de nós vazios estarem no final da árvore e certamente não ganhará nenhum prêmio por brevidade, mas acho que está correto e tem casos de teste :)
fonte
Golfe (
9989)Basicamente, uma porta direta da minha solução Python, funciona da mesma maneira.
Provavelmente pode ser melhorado um pouco com mais "golfismos", já melhorado em 10 caracteres com a entrada de @ petertaylor :)
fonte
!{;}{}if
pode ser apenas!{;}*
porque!
garante a devolução0
ou1
. Você pode usar símbolos não alfabéticos para variáveis, por isso, se você usa^
em vez der
,|
em vez dex
,&
em vez dey
você pode eliminar tudo o que os espaços em branco.Java 192
Mapeia o índice na entrada para o índice na saída
Versão longa:
fonte
Wolfram Mathematica 11, 175 bytes
A função
g[l]
recebe como entrada aList
(por exemplol={1,2,3,4,...}
) e retorna aList
da forma desejada. Funciona da seguinte maneira:x[a_]:=Floor@Min[i-#/2,#]&@(i=Length[a]+1;2^Ceiling@Log2[i]/2)
pega uma lista e encontra a raiz do BST associado.i=Length[a]+1
atalho para o comprimento da lista2^Ceiling@Log2[i]/2
limite superior do valor da raizMin[i-#/2,#]&@(...)
O mínimo dos dois argumentos em que#
representa o que está dentro do(...)
l//.{...}
Aplique repetidamente as regras de substituição a seguir paral
{}->{}
Nada a fazer (este é o caso extremo para evitar um loop infinito)b__List:>(n[Take[b,#-1],b[[#]],Drop[b,#]]&@x[b])
Dividir umList
em{{lesser}, root, {greater}}
Cases[...,_Integer,{m}]
Pegue todos os números inteiros no nível (profundidade)m
Table[...,{m,1,x[l]}]
Para todos,m
atéx[l]
(o que é mais do que necessário, na verdade).Pode ser testado executando
Esta implementação não inclui zeros à direita.
fonte
Python (
175171)Bastante condensado, ainda bastante legível;
Ele retorna o resultado, então você pode fazer um loop sobre ele ou (para fins de exibição) imprimi-lo como uma lista;
fonte
Java
Esta é uma solução de cálculo direto. Eu acho que funciona, mas tem um efeito colateral pragmaticamente inócuo. A matriz que produz pode estar corrompida, mas não de maneira alguma que afete as pesquisas. Em vez de produzir 0 nós (nulos), ele produzirá nós inacessíveis, ou seja, os nós já foram encontrados anteriormente na árvore durante a pesquisa. Ele funciona mapeando a matriz de índices de uma potência regular de matriz de árvore de pesquisa binária de 2 tamanhos em uma matriz de árvore de pesquisa binária de tamanho irregular. Pelo menos, acho que funciona.
Aqui está uma versão mais resumida (apenas a função e os nomes emparelhados). Ainda tem espaço em branco, mas não estou preocupado em ganhar. Além disso, esta versão leva uma matriz. O outro levou apenas um int para o índice mais alto da matriz.
fonte
GolfScript (
79 7770 caracteres)Como o exemplo da pergunta usa uma função, eu fiz disso uma função. A remoção de
{}:f;
para deixar uma expressão que recebe entrada na pilha e deixa o BST na pilha economizaria 5 caracteres.Demonstração online (observação: o aplicativo pode demorar um pouco: se esgotou o tempo limite para mim antes de ser executado em 3 segundos).
Com espaço em branco para mostrar a estrutura:
fonte
J , 52 bytes
A função pega uma lista classificada e retorna em ordem de árvore binária
Observe que as árvores têm forma idêntica, mas o nível inferior é reduzido
`1:
comece com 1<.@(2&^.)@>:@#
itera pelo piso de log2 (comprimento + 1)+: , >:@+:@i.@>:@#
loop: acrescenta o dobro do último vetor com números ímpares 1,3 .. 2 * comprimento + 1# /:@{.
pegue apenas o número necessário de itens e obtenha seus índices de classificação/:
aplicar esses índices de classificação à entrada especificadaTIO
fonte
Python 2 , 107 bytes
Golfe da resposta de Joachim Isaksson , Input é um singleton que contém a lista.
Experimente online!
fonte